CF767C Garland--树形dp
Posted snowy2002
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF767C Garland--树形dp相关的知识,希望对你有一定的参考价值。
今天无聊的我又来切树形dp了,貌似我与树形dp有仇似的。
n个节点的树
第i个节点权值为 n<=10^6
?100<=ai?<=100
问是否能够删除掉两条边,使得该树分成三个不为空,并且每部分权值之和相等.
无解输出?1 否则输出要删除边(u?>v)的v节点序号.
说白了就是把一棵树分成三块连通图,并且每个连通图权值相同,那么我们不管怎么切都会切出以某个结点为根的子树。由于每个点的权值都是整数,那么我们先用总权值 mod 3看看能不能整除,如果不能就输出-1,如果可以那么每个子树肯定权值都是 w/3 (w为总权值)。接着就跑树形dp咯,设f[x]代表以x为根的子树的权值和(包括x在内),如果某一个f[x]== w/3 我们就统计一下,如果一个树上有三个这样的根节点,那么就把这三个根节点和他们的父亲的边切了,这样就得到了我们想要的结果了,所以统计一下这样的点的数量就行,最后判断一下是否三个这样的点。
接下来就是愉快的代码时间:
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cmath> 5 #include<cstring> 6 #include<queue> 7 #include<stack> 8 #include<algorithm> 9 #define maxn 1000005 10 using namespace std; 11 12 struct edge 13 { 14 int next; 15 int to; 16 }g[maxn<<1]; 17 18 inline int read() 19 { 20 char c=getchar(); 21 int res=0,x=1; 22 while(c<‘0‘||c>‘9‘) 23 { 24 if(c==‘-‘) 25 x=-1; 26 c=getchar(); 27 } 28 while(c>=‘0‘&&c<=‘9‘) 29 { 30 res=res*10+(c-‘0‘); 31 c=getchar(); 32 } 33 return x*res; 34 } 35 36 int n,num,aa,bb,root,sum,cnt,ans[10]; 37 int last[maxn],f[maxn],d[maxn]; 38 39 inline void add(int from,int to) 40 { 41 g[++num].next=last[from]; 42 g[num].to=to; 43 last[from]=num; 44 } 45 46 void dfs(int x) 47 { 48 d[x]=1; 49 for(int i=last[x];i;i=g[i].next) 50 { 51 int v=g[i].to; 52 if(!d[v]) 53 { 54 dfs(v); 55 f[x]+=f[v]; 56 } 57 } 58 if(f[x]==sum) 59 { 60 ans[++cnt]=x; 61 f[x]=0; 62 } 63 } 64 65 int main() 66 { 67 n=read(); 68 for(int i=1;i<=n;i++) 69 { 70 aa=read();bb=read(); 71 f[i]=bb; 72 sum+=bb; 73 if(aa==0) 74 { 75 root=i; 76 } 77 else 78 { 79 add(i,aa); 80 add(aa,i); 81 } 82 } 83 if(sum%3!=0) 84 { 85 printf("-1 "); 86 return 0; 87 } 88 else 89 { 90 sum=sum/3; 91 dfs(root); 92 if(cnt<=2) 93 printf("-1"); 94 else 95 printf("%d %d",ans[1],ans[2]); 96 return 0; 97 } 98 }
If you fail, don‘t forget to learn your lesson.
如果你失败了,千万别忘了汲取教训。
--snowy
2019-01-16 12:02:52
以上是关于CF767C Garland--树形dp的主要内容,如果未能解决你的问题,请参考以下文章