重心-[Codeforces709E] Centroids
来源:互联网 发布:关于网络舆论的法律 编辑:程序博客网 时间:2024/06/07 05:12
题目就是给出一颗树,对于每一个点,如果改变树的一条边(可以不变),是否能让这个点变成重心;
zzh学长教我时,告诉我这是贪心(其实好像是树形dp),因为重心的最大的子树大小不超过全树的一半,所以贪心也是方便的,即尽可能让某个点的最大的子树大小不超过全树的一半;所谓改变一条边,显然是在某点的最大的子树里砍掉一边,添加到别的地方,这样可以使整棵树相对于这个点更平衡;
但是我们要删掉哪一条边,添加到哪里,这就要贪心了;
设询问某点x
我们知道,原先的树也是有重心的,设其是y;显然,y一定在x的最大的子树里;如果我们要建立一个新的重心x,就一定要破坏原先的重心y,很显然,改变的最优方法必然是在原重心y附近截取一个子树移到x上;
显然的,割掉原先y的最大子树接到x上是比较好的,因为y的最大子树一定不超过全树的一半,且去掉y的最大子接到x上,重心一定会从y向x移;感觉就是这样,把y的最大子树移动到x上,最优;
但本蒟蒻无法证明~~~;
当然咯,如果x恰好就在y的最大子树上,那就尴尬了,要判断两种较优情况
1.取y的次大子树接到x上;
2.把割掉y的最大子树后的那颗树接到x上;
就是这样,感觉这个贪心蒙出来的,还是dp靠谱
如果原来有好多重心,任意
#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>#define LL long longusing namespace std;struct cs{ int to,next;}a[800009];int head[400010],v[400005],vv[400005];//链表存,v[i]是i节点的最大子树,vv[i]是次大 bool b[400005];//标记点i是否在原重心的最大子树上 int n,m,x,y,ans,ll,maxc,z;void inc(int x,int y){ ll++; a[ll].to=y; a[ll].next=head[x]; head[x]=ll;}int dfs(int x,int y){ int k=head[x],an1=0,an=0,c=0,ann=0; int sum=1; while(k){ if(a[k].to!=y)an=dfs(a[k].to,x);else an=0; sum+=an; if(an>an1){ if(an1>ann)ann=an1; an1=an;c=a[k].to; }else if(an>ann)ann=an; k=a[k].next; } an=n-sum; if(an>an1){ if(an1>ann)ann=an1; an1=an;c=y; }else if(an>ann)ann=an; v[x]=an1;vv[x]=ann; if(an1<=n/2){ ans=x;maxc=c; } return sum;}int dfs2(int x,int y){ int k=head[x]; while(k){ if(a[k].to!=y){ b[a[k].to]=1; dfs2(a[k].to,x); } k=a[k].next; }}int main(){ memset(head,0,sizeof head); ll=0; scanf("%d",&n); for(int i=1;i<=n-1;i++){ scanf("%d%d",&x,&y); inc(x,y); inc(y,x); } int k=head[1],an1=0,an=0,c=0,ann=0; while(k){ an=dfs(a[k].to,1); if(an>an1){ if(an1>ann)ann=an1; an1=an;c=a[k].to; }else if(an>ann)ann=an; k=a[k].next; } v[1]=an1; vv[1]=ann; if(an1<=n/2){ ans=1;maxc=c; } b[maxc]=1; dfs2(maxc,ans); for(int i=1;i<=n;i++){ if(b[i]){ if(max(v[i]-vv[ans],vv[ans])<=n/2){printf("1 ");continue;} if(n-v[ans]<=n/2){printf("1 ");continue;} printf("0 "); }else{ if(max(v[ans],v[i]-v[ans])<=n/2){printf("1 ");continue;} printf("0 "); } }}
1 0
- 重心-[Codeforces709E] Centroids
- CF708C:Centroids(树形dp & 重心构造判断)
- [CF708C]Centroids
- AIM Tech Round 3 (Div. 1) C. Centroids(每个点能否删掉一条边再添加一条边使得这个点成为重心)
- 【Codeforces708C】【树形dp】【贪心】Centroids
- 【CF 708C】Centroids(树型DP)
- Codeforces 708C Centroids(树形dp)
- 树形dp(Centroids,cf 708C)
- CF 708C. Centroids 树形dp
- 重心坐标
- 求重心
- 三角形重心
- 多边形重心
- 多边形重心
- 多边形重心
- 求重心
- 多边形重心
- 重走一遍不重心
- 使用IDEA创建Struts项目
- 153. Find Minimum in Rotated Sorted Array
- 209. Minimum Size Subarray Sum
- html,css简单仿站之建材网
- JAVA高精度1_大数相加_阶乘
- 重心-[Codeforces709E] Centroids
- linux文件系统
- Nginx源码阅读(ngx_pool_t)
- 基于环信的仿QQ即时通讯的简单实现
- boolan——c++学习笔记之内存分配
- memory_target指定的值过小
- systemctl命令
- 8VC Venture Cup 2017 - Elimination Round D. PolandBall and Polygon
- js组合模式及宏命令