cf1118f1

题意:

给定一棵树,树上的点有0,1,2三中情况,0代表该点无色。现在需要你将这棵树割掉一些边,使得割掉每条边分割成的两部分均最多只含有一种颜色的点,即分割后的两部分不能1,2点夹杂(0的点数可以任意),问你最多能有几条这样的割点。

dfs求解出所有点以自己为根的子树 i 中1,2,节点的个数num1,num2,然后根据母树与子树之间的num1,num2值做差,能够得到 i 的另一部分的1,2,节点个数,然后再判断这两部分是否符合条件即可。

 

#include"stdio.h"
#include"string.h"
#include"algorithm"
using namespace std;

const int N = 20010,M = 1001010;
int head[N],ver[M],Next[M],tot;
int a[N],n;
int num1[N],num2[N];

void add(int x,int y)
{
    ver[++ tot] = y; Next[tot] = head[x]; head[x] = tot;
}

void dfs(int x,int far)
{
    if(a[x] == 1) num1[x] = 1;
    else if(a[x] == 2)num2[x] = 1;
    for(int i = head[x]; i; i = Next[i]){
        int y = ver[i];
        if(y == far) continue;
        dfs(y,x);
        num1[x] += num1[y];
        num2[x] += num2[y];
    }
}
int main()
{
    scanf("%d",&n);
    for(int i = 1; i <= n; i ++) scanf("%d",&a[i]);
    for(int i = 1; i < n; i ++){
        int x,y; scanf("%d%d",&x,&y);
        add(x,y); add(y,x);
    }
    dfs(1,-1);
    int ans = 0;
    for(int i = 2; i <= n; i ++){
        int x = num1[1] - num1[i];
        int y = num2[1] - num2[i];
        if(num1[i] && num2[i]) continue;
        else if(x == 0 || y == 0) ans ++;
    }
     printf("%d\n",ans);
}

 

posted @ 2020-03-04 01:26  风生  阅读(249)  评论(0编辑  收藏  举报