首先翻得顺序一定是按照树的深度,由上至下,每遇到一个不一样的就要翻,然后更新这个子树。但是这样显然是超时的。
实际上在一棵子树中,按照层次的奇偶性可以分成两个集合,设为a,b,如果根节点在a集合,并且要修改,那么修改的就是b集合,反正一样。于是就从根节点开始DFS,每向下搜一层,层次的奇偶就发生了互换,所以交换a1,a2。
输入给的边不一定是什么方向的,邻接表要全都添加,然后DFS时开vis数组判断。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#include <vector>
#include <queue>
vector <int > G[100005];
int N;
int pre[100005];
int ord[100005];
int res[100005];
int rnum;
bool vis[100005];
void solve(int n,int a1,int a2){
if((pre[n]^a1)!=ord[n]){
res[++rnum]=n;
a1=!a1;
}
for(int i=0;i<G[n].size();i++){
if(!vis[G[n][i]]){
vis[G[n][i]]=1;
solve(G[n][i],a2,a1);
}
}
}
int main(){
scanf("%d",&N);
for(int i=1;i<N;i++){
int s,t;
scanf("%d%d",&s,&t);
G[t].push_back(s);
G[s].push_back(t);
}
for(int i=1;i<=N;i++){
scanf("%d",&pre[i]);
}
for(int i=1;i<=N;i++){
scanf("%d",&ord[i]);
}
vis[1]=1;
solve(1,0,0);
printf("%d\n",rnum);
for(int i=1;i<=rnum;i++){
printf("%d\n",res[i]);
}
return 0;
}