Codeforces 1118F1 Tree Cutting (Easy Version) (简单树形DP)
<题目链接>
题目大意:
给定一棵树,树上的点有0,1,2三中情况,0代表该点无色。现在需要你将这棵树割掉一些边,使得割掉每条边分割成的两部分均最多只含有一种颜色的点,即分割后的两部分不能1,2点夹杂(0的点数可以任意),问你最多能有几条这样的割点。
解题分析:
dfs求解出所有点以自己为根的子树 i 中1,2,节点的个数num1,num2,然后根据母树与子树之间的num1,num2值做差,能够得到 i 的另一部分的1,2,节点个数,然后再判断这两部分是否符合条件即可。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N int(3e5+7) 5 #define rep(i,s,t) for(int i=s;i<=t;i++) 6 #define pb push_back 7 int n; 8 int col[N],num1[N],num2[N]; 9 vector<int>G[N]; 10 11 void dfs(int u,int pre){ 12 if(col[u]==1)num1[u]=1; 13 if(col[u]==2)num2[u]=1; 14 for(int i=0;i<G[u].size();i++){ 15 int v=G[u][i]; 16 if(v==pre)continue; 17 dfs(v,u); 18 num1[u]+=num1[v],num2[u]+=num2[v]; //得到每个以u为根的子树的1、2节点的个数 19 } 20 } 21 22 int main(){ 23 scanf("%d",&n); 24 for(int i=1;i<=n;i++)scanf("%d",&col[i]); 25 for(int i=1;i<n;i++){ 26 int u,v;scanf("%d%d",&u,&v); 27 G[u].pb(v);G[v].pb(u); 28 } 29 dfs(1,-1); 30 int ans=0; 31 for(int i=2;i<=n;i++){ //以1节点为整棵树的根节点 32 int x=num1[1]-num1[i]; 33 int y=num2[1]-num2[i]; 34 if(num1[i]&&num2[i])continue; //如果以i为根的子树含有两种颜色,它与它pre节点的边即使断开,也不符合 35 else if(x==0||y==0)ans++; //在上一句的情况下,如果整棵树以i为根的1、2节点个数有一个为0,那么将i与其pre节点之间的边断开成的两部分是符合条件的 36 } 37 printf("%d\n",ans); 38 }
2019-02-22
作者:is_ok
出处:http://www.cnblogs.com/00isok/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。