博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【uoj#139】[UER #4]被删除的黑白树 贪心
阅读量:5055 次
发布时间:2019-06-12

本文共 1216 字,大约阅读时间需要 4 分钟。

给出一个 $n$ 个节点的树,$1$ 号点为根。现要将其中一些点染成黑色,使得每个叶子节点(不包括根节点)到根节点路径上的黑点数相同。求最多能够染多少个黑点。


题解

贪心

显然有结论:选择的黑点尽量靠近叶子节点。

并且显然每个点到根节点路径上的黑点数是:深度最小的叶子节点到根节点路径上的点数。

那么首先预处理出每个点子树内深度最小的叶子节点的深度,然后进行贪心过程:显然如果一个点染黑,那么它到其子树内深度最小的叶子节点路径上的所有点都要染黑。我们维护每个点到根节点的路径上染了多少黑点,就能根据已经染黑的节点数和它到其字数内深度最小的叶子节点路径上的点数即可判断出当前点是否能够选择。

时间复杂度 $O(n)$

#include 
#include
#define N 100010using namespace std;int head[N] , to[N << 1] , next[N << 1] , cnt , deep[N] , md[N] , now[N] , ans;inline void add(int x , int y){ to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;}void dfs(int x , int fa){ int i; if(x != 1 && !next[head[x]]) md[x] = deep[x]; else md[x] = 1 << 30; for(i = head[x] ; i ; i = next[i]) if(to[i] != fa) deep[to[i]] = deep[x] + 1 , dfs(to[i] , x) , md[x] = min(md[x] , md[to[i]]);}void solve(int x , int fa){ int i; now[x] = now[fa]; if(now[fa] + md[x] - deep[x] == md[1]) now[x] ++ , ans ++ ; for(i = head[x] ; i ; i = next[i]) if(to[i] != fa) solve(to[i] , x);}int main(){ int n , i , x , y; scanf("%d" , &n); for(i = 1 ; i < n ; i ++ ) scanf("%d%d" , &x , &y) , add(x , y) , add(y , x); dfs(1 , 0); solve(1 , 0); printf("%d\n" , ans); return 0;}

 

转载于:https://www.cnblogs.com/GXZlegend/p/8244237.html

你可能感兴趣的文章
css3动画——基本准则
查看>>
javaweb常识
查看>>
Java注解
查看>>
web自己主动保存表单
查看>>
一个小的日常实践——高速Fibonacci数算法
查看>>
机器学些技法(9)--Decision Tree
查看>>
drf权限组件
查看>>
输入月份和日期,得出是今年第几天
查看>>
【linux】重置fedora root密码
查看>>
pig自定义UDF
查看>>
Kubernetes 运维学习笔记
查看>>
spring security 11种过滤器介绍
查看>>
图解算法时间复杂度
查看>>
UI_搭建MVC
查看>>
一个样例看清楚JQuery子元素选择器children()和find()的差别
查看>>
代码实现导航栏分割线
查看>>
Windows Phone开发(7):当好总舵主 转:http://blog.csdn.net/tcjiaan/article/details/7281421...
查看>>
VS 2010打开设计器出现错误
查看>>
SQLServer 镜像功能完全实现
查看>>
Vue-详解设置路由导航的两种方法
查看>>