codeforces百题计划第一周(5)
(1)一开始树形dp写了半天(真的是半天),没过,看了题解,用了很巧妙的方法。
对于对于每条两端颜色不同的边,都需要切断,才可以满足要求。
因为只能删除一个点,那也就是这些有不同颜色端点的边都连在一个点上,那么才能通过删掉这个点把树分成几个纯色子树。
每找到一条这样的边,异色边E++,两个端点num[u]++,num[v]++。最后找最大num[i],如果等于E,一定可以通过删除i满足要求。
(2)感觉树形dp也行的,但是没写好,过了一半测试点,改一点,多过几个,实在不想改了。
对于当前节点v,记录v上面点的颜色数,再统计v节点的每一颗子树的颜色,如果,每颗子树的颜色数是1,v节点上方的颜色数也是1,那么删除v节点可以满足要求。
两次dfs,一次向上,一次回溯。思路应该没有问题,但是写炸了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=2e5+5; 5 6 7 int num[maxn]; 8 int c[maxn]; 9 struct node{ 10 int u;int v; 11 }e[maxn]; 12 13 14 int main() 15 { 16 int n;scanf("%d",&n); 17 for(int i=1;i<n;i++) 18 { 19 int u,v; 20 scanf("%d%d",&e[i].u,&e[i].v); 21 } 22 for(int i=1;i<=n;i++) 23 { 24 scanf("%d",&c[i]); 25 } 26 int m=0; 27 for(int i=1;i<n;i++) 28 { 29 //cout <<e[i].u<<" "<<e[i].v<<endl; 30 if(c[e[i].u]!=c[e[i].v]) m++,num[e[i].u]++,num[e[i].v]++; 31 } 32 int maa=num[1];int ans=1; 33 for(int i=2;i<=n;i++) 34 { 35 if(num[i]>maa) maa=num[i],ans=i; 36 } 37 //cout <<m<<" "<<maa<<endl; 38 if(maa==m) printf("YES\n%d\n",ans); 39 else printf("NO\n"); 40 return 0; 41 }