题目大意:给你一棵有n个节点的树,每个节点的value为0或1,给你初始value和目标value,对于每个节点可以执行一种操作:将该节点的value变为相反的即0变为1,1变为0,同时给节点的孙子节点,孙子节点的孙子都变反。问,最少进行多少次操作可以将初始value变为目标value,输出操作次数和需要更改的节点。
操作次数最少,明显从上往下修改, 如何判断一个点是否受祖先结点影响而被修改? 当前结点受祖先影响,被修改的次数为奇数次
记录一个点被修改和不被修改的次数c,d,遇到要修改的记录即可.
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+20;
vector<int> e[N];
int n,a[N],g[N],vis[N],ans;
//c,d 受所选的点影响:被修改的次数和没被修改的次数
void dfs(int u,int fa,int c,int d)
{
int flag=0;
if(c%2)
flag=1;
if(a[u]^flag!=g[u])
{
ans++;
vis[u]=1;
c++;
}
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i];
if(v==fa) continue;
dfs(v,u,d,c);
}
}
int main()
{
while(cin>>n)
{
ans=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n-1;i++)
{
int u,v;
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&g[i]);
dfs(1,0,0,0);
cout<<ans<<endl;
for(int i=1;i<=n;i++)
{
if(vis[i])
cout<<i<<endl;
e[i].clear();
}
}
return 0;
}