BZOJ 2525 [Poi2011]Dynamite 二分+树形贪心
2015-10-03 22:48
344 查看
题意:
n个点,一棵树,有些点是关键点,可以将m个点染色。
求所有关键点到最近的被染色点的距离的最大值最小。
解析:
反正从这道题我是学了一种做题思路?
大爷讲课的时候说的:一般选择某些点的代价相同的话都是贪心,代价不同的话一般都是DP。
想想也挺对的,不过就是没有感悟到过?
反正这题考试的时候我是直接D了贪心的- -!
忘了为啥D了。
显然最大值最小我们需要二分一下这个值。
然后接下来我们从下往上扫整棵树。
节点的状态有几个?
第一种是 子树内没有不被覆盖的关键点,并且子树中有一个节点的贡献可以继续往上。
第二种是 子树内有不被覆盖的关键点,子树中没有节点的贡献可以继续往上。
第三种是 既没有 不被覆盖的关键点,又没有 可以继续往上贡献的点。
第四种是 都有。
但是 我们可以证明,第四种情况存在的话,显然可以在子树外挑一个点来覆盖没有被覆盖的关键点,但是这个时候子树内的挑选的点就没有卵用了,所以这种情况可以归到第三种。
然后具体就是我们贪心讨论的过程了。
贪心的思想就是,能不染就不染
显然第一种我们需要记录还能往上走多少。
第二种我们需要记录最远的不被覆盖的关键点到达目前的根节点的距离
我觉得做法什么的比较次要吧。
还是这句话
一般选择某些点的代价相同的话都是贪心,代价不同的话一般都是DP。
也许这句话能解决我今后贪心和DP的困扰?2333
代码:
n个点,一棵树,有些点是关键点,可以将m个点染色。
求所有关键点到最近的被染色点的距离的最大值最小。
解析:
反正从这道题我是学了一种做题思路?
大爷讲课的时候说的:一般选择某些点的代价相同的话都是贪心,代价不同的话一般都是DP。
想想也挺对的,不过就是没有感悟到过?
反正这题考试的时候我是直接D了贪心的- -!
忘了为啥D了。
显然最大值最小我们需要二分一下这个值。
然后接下来我们从下往上扫整棵树。
节点的状态有几个?
第一种是 子树内没有不被覆盖的关键点,并且子树中有一个节点的贡献可以继续往上。
第二种是 子树内有不被覆盖的关键点,子树中没有节点的贡献可以继续往上。
第三种是 既没有 不被覆盖的关键点,又没有 可以继续往上贡献的点。
第四种是 都有。
但是 我们可以证明,第四种情况存在的话,显然可以在子树外挑一个点来覆盖没有被覆盖的关键点,但是这个时候子树内的挑选的点就没有卵用了,所以这种情况可以归到第三种。
然后具体就是我们贪心讨论的过程了。
贪心的思想就是,能不染就不染
显然第一种我们需要记录还能往上走多少。
第二种我们需要记录最远的不被覆盖的关键点到达目前的根节点的距离
我觉得做法什么的比较次要吧。
还是这句话
一般选择某些点的代价相同的话都是贪心,代价不同的话一般都是DP。
也许这句话能解决我今后贪心和DP的困扰?2333
代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 300100 using namespace std; int n,m; int flag ; int head ; int status ; int document ; int cnt; int tot; struct node { int from,to,next; }edge[N<<1]; void init() { memset(head,-1,sizeof(head)); cnt=1; } void edgeadd(int from,int to) { edge[cnt].from=from,edge[cnt].to=to; edge[cnt].next=head[from]; head[from]=cnt++; } // 0-> 继续传递 // 1-> 有未被覆盖 // 2-> 既没有传递也没有未被覆盖。 void dfs(int now,int fa,int dis) { int uncovered=flag[now]-1; int near=-1; for(int i=head[now];i!=-1;i=edge[i].next) { int to=edge[i].to; if(to==fa)continue; dfs(to,now,dis); } for(int i=head[now];i!=-1;i=edge[i].next) { int to=edge[i].to; if(to==fa)continue; if(status[to]==0) near=max(near,document[to]-1); else if(status[to]==1)uncovered=max(uncovered,document[to]+1); } if(near<uncovered) { if(uncovered==dis) document[now]=dis,status[now]=0,tot++; else document[now]=uncovered,status[now]=1; }else if(near!=-1)document[now]=near,status[now]=0; else status[now]=2,document[now]=0; } bool check(int dis) { tot=0; dfs(1,0,dis); if(status[1]==1)tot++; return tot<=m?1:0; } int main() { init(); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&flag[i]); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); edgeadd(x,y); edgeadd(y,x); } int l=0,r=n,ans; while(l<=r) { int mid=(l+r)>>1; if(check(mid))ans=mid,r=mid-1; else l=mid+1; } printf("%d\n",ans); }
相关文章推荐
- 产品心理学-知觉四特性教你如何给产品做减法
- 剑指offer—二叉搜索树的后序遍历序列
- Facebook如何使用“我们”的数据去构建人工智能
- 数据库范式
- HDOJ 5494 Card Game(水)
- 感悟--网络找答案
- Web Service:HTTP协议
- DirectX11 板条箱示例Demo
- 功能测试 黑盒测试方法
- ZOJ3822-Domination 概率DP
- 动态计算UITableViewCell高度详解
- hdu 1242 Rescue(bfs+优先队列)
- Hadoop学习笔记(六)启动Shell分析
- Python文件名称与将导入的模块名相同会出现的问题
- SPOJ QTREE - Query on a tree(树链剖分)
- SGU 258 Almost Lucky Numbers 接近幸运数(数位DP)
- 项目问题思考之策略模式
- 找出第二个文本抄袭第一个文本的所有位置和长度 后缀数组 UVA 10526 - Intellectual Property
- 【bzoj3034】Heaven Cow与God Bull
- 剑指offer—从上往下打印二叉树