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 
 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){
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){
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

转载于:https://www.cnblogs.com/00isok/p/10417040.html

你可能感兴趣的:(Codeforces 1118F1 Tree Cutting (Easy Version) (简单树形DP))