Codeforces 430C Xor-tree【Dfs+思维】

来源:互联网 发布:淘宝垃圾箱在哪 编辑:程序博客网 时间:2024/05/22 17:30

A. Xor-tree
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Iahub is very proud of his recent discovery, propagating trees. Right now, he invented a new tree, called xor-tree. After this new revolutionary discovery, he invented a game for kids which uses xor-trees.

The game is played on a tree having n nodes, numbered from1 to n. Each nodei has an initial value initi, which is either 0 or 1. The root of the tree is node 1.

One can perform several (possibly, zero) operations on the tree during the game. The only available type of operation is to pick a nodex. Right after someone has picked node x, the value of node x flips, the values of sons ofx remain the same, the values of sons of sons ofx flips, the values of sons of sons of sons ofx remain the same and so on.

The goal of the game is to get each node i to have valuegoali, which can also be only 0 or 1. You need to reach the goal of the game by using minimum number of operations.

Input

The first line contains an integer n (1 ≤ n ≤ 105). Each of the nextn - 1 lines contains two integers ui and vi (1 ≤ ui, vi ≤ n;ui ≠ vi) meaning there is an edge between nodesui andvi.

The next line contains n integer numbers, thei-th of them corresponds to initi (initi is either 0 or 1). The following line also containsn integer numbers, the i-th number corresponds to goali (goali is either 0 or 1).

Output

In the first line output an integer number cnt, representing the minimal number of operations you perform. Each of the nextcnt lines should contain an integer xi, representing that you pick a nodexi.

Examples
Input
102 13 14 25 16 27 58 69 810 51 0 1 1 0 1 0 1 0 11 0 1 0 0 1 1 1 0 1
Output
247

题目大意:

给你一个以节点1为根的一棵树,给你所有点的初始权值(只有0或者1),以及想要变成的所有点的最终权值(也是只有0或者1);

我们可以通过选择一个点X,将点X的权值进行翻转(0和1调换),带来的变化还有:其X的儿子的儿子的权值也要翻转,其儿子的儿子的儿子的儿子的权值也要翻转。

问最少选择几个点,就能够达到最终目的。


思路:


1、对于一棵树,父亲只能影响其儿子的变化,而儿子不能改变父亲的变化。那么我们按照深度优先的顺序遍历这棵树,那么很明显,如果当前这个节点的权值需要变化,那么肯定就要选择这个节点一次,将本身的权值翻转,然后对其所有的儿子的权值都要翻转。然后继续深度优先遍历。


2、对于一棵树,奇数层数的节点只受奇数层数的节点的限制,偶数层数的节点只受偶数层数的节点的限制,所以我们Dfs整颗树,如果当前遇到的这个点对应翻转其上边的节点累加的翻转次数之后变成的数值和最终数值不相同,那么对应将这个节点我们要选择翻转一次,然后再累加当前奇数/偶数层次的翻转次数,等到其所有子树都遍历结束之后,回溯到当前节点的时候,别忘记清除累加次数,因为再回溯到上边之后,是不需要累加这个节点的操作次数的。


3、谨慎一些实现代码即可。


Ac代码:

#include<stdio.h>#include<string.h>#include<vector>using namespace std;vector<int >mp[107000];int a[107000];int b[107000];int vis[107000];int ans[107000];int ji,ou,cont;void Dfs(int u,int level){    vis[u]=1;    int tmp;    if(level%2==1)tmp=ji;    else tmp=ou;    int flag=0;    if((a[u]^tmp)!=b[u])    {        flag=1;        a[u]=b[u];        ans[cont++]=u;        if(level%2==1)ji^=1;        else ou^=1;    }    for(int i=0;i<mp[u].size();i++)    {        int v=mp[u][i];        if(vis[v]==0)        {            Dfs(v,level+1);        }    }    if(flag==1)    {        if(level%2==1)ji^=1;        else ou^=1;    }}int main(){    int n;    while(~scanf("%d",&n))    {        memset(vis,0,sizeof(vis));        for(int i=1;i<=n;i++)mp[i].clear();        for(int i=1;i<=n-1;i++)        {            int x,y;            scanf("%d%d",&x,&y);            mp[x].push_back(y);            mp[y].push_back(x);        }        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i]);        }        for(int i=1;i<=n;i++)        {            scanf("%d",&b[i]);        }        cont=0;        ji=0;        ou=0;        Dfs(1,1);        printf("%d\n",cont);        for(int i=0;i<cont;i++)        {            printf("%d\n",ans[i]);        }    }}










0 0
原创粉丝点击