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); }