题意:
给你一棵树,每个节点都有一个颜色,不是黑就是白,你每次可以选择一个节点,将这个节点的颜色翻转,同时这个点所有孙子的颜色也会全部被翻转,孙子的孙子颜色也会全部被翻转……
问至少操作多少次使得所有节点的颜色满足题目要求,输出每次操作的节点
思路:
从根开始按照节点的深度遍历,如果这个点的颜色不满足要求,直接翻转就可以了,BFS一遍即可
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
int inv[100005][2], ans[100005], val[100005], flag[100005];
queue<int> q;
vector<int> G[100005];
int main(void)
{
int cnt, x, y, n, i;
scanf("%d", &n);
for(i=1;i<=n-1;i++)
{
scanf("%d%d", &x, &y);
G[x].push_back(y);
G[y].push_back(x);
}
for(i=1;i<=n;i++)
scanf("%d", &val[i]);
for(i=1;i<=n;i++)
{
scanf("%d", &x);
val[i] = val[i]^x;
}
q.push(1);
flag[1] = 1, cnt = 0;
while(q.empty()==0)
{
x = q.front();
q.pop();
val[x] ^= inv[x][1];
if(val[x]==1)
ans[++cnt] = x;
for(i=0;i<G[x].size();i++)
{
y = G[x][i];
if(flag[y])
continue;
inv[y][0] ^= val[x]^inv[x][1];
inv[y][1] ^= inv[x][0];
flag[y] = 1;
q.push(y);
}
}
printf("%d\n", cnt);
for(i=1;i<=cnt;i++)
printf("%d ", ans[i]);
puts("");
return 0;
}