题目大意:给你一棵有n个节点的树,每个节点的value为0或1,给你初始value和目标value,对于每个节点课以执行一种操作:将该节点的value变为相反的即0变为1,1变为0,同时给节点的孙子节点,孙子节点的孙子都变反。问,最少进行多少次操作可以将初始value变为目标value,输出操作次数和需要更改的节点。
思路:记录每个节点需要变num1和不需要变num2的次数,那么他的儿子结点变不变可以由父节点的值得出。若进行了相应变换后与目标value不同,则进行一次操作,并更新num1和num2的值。进行一次BFS即可。
#include <algorithm>
#include <set>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <iostream>
using namespace std;
#define maxn 1000010
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
int a[110000] , b[110000];
int ans[110000];
int n;
vector<int>V[110000];
int vis[110000];
struct node
{
int val;
int num1;
int num2;
}tmp , tmp2;
int main()
{
int t;
while(scanf("%d" , &n) != EOF)
{
mem(vis , 0);
for(int i = 0 ; i <= n ; i ++) V[i].clear();
int u ,v;
for(int i = 0 ; i < n - 1 ; i ++)
{
scanf("%d %d" , &u , &v);
V[u].push_back(v);
V[v].push_back(u);
}
for(int i = 1 ; i <= n ; i ++) scanf("%d" , &a[i]);
for(int i = 1 ; i <= n ; i ++) scanf("%d" , &b[i]);
int pos = 0;
queue<node>q;
while(!q.empty()) q.pop();
tmp.val = 1;
tmp.num1 = tmp.num2 = 0;
q.push(tmp);
vis[1] = 1;
while(!q.empty())
{
tmp = q.front();
q.pop();
if(a[tmp.val] == b[tmp.val])
{
int len = V[tmp.val].size();
for(int i = 0 ; i < len ; i ++)
{
if(vis[V[tmp.val][i]]) continue;
tmp2.val = V[tmp.val][i];
tmp2.num1 = tmp.num2;
tmp2.num2 = tmp.num1;
if(tmp2.num1 % 2)
{
if(a[tmp2.val] == 0 ) a[tmp2.val] = 1;
else a[tmp2.val] = 0;
}
q.push(tmp2);
vis[tmp2.val] = 1;
}
}
else
{
ans[pos++] = tmp.val;
a[tmp.val] = b[tmp.val];
int len = V[tmp.val].size();
for(int i = 0 ; i < len ; i ++)
{
if(vis[V[tmp.val][i]]) continue;
tmp2.val = V[tmp.val][i];
tmp2.num1 = tmp.num2 ;
tmp2.num2 = tmp.num1 + 1;
if(tmp2.num1 % 2)
{
if(a[tmp2.val] == 0 ) a[tmp2.val] = 1;
else a[tmp2.val] = 0;
}
q.push(tmp2);
vis[tmp2.val] = 1;
}
}
}
cout << pos << endl;
//sort(ans , ans + pos);
for(int i = 0 ; i < pos ; i ++)
{
printf("%d\n" , ans[i]);
}
}
return 0;
}