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

224 篇文章 2 订阅

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 from 1 to n. Each node i 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 node x. Right after someone has picked node x, the value of node x flips, the values of sons of x remain the same, the values of sons of sons of x flips, the values of sons of sons of sons of x remain the same and so on.

The goal of the game is to get each node i to have value goali, 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 next n - 1 lines contains two integers ui and vi (1 ≤ ui, vi ≤ n; ui ≠ vi) meaning there is an edge between nodes ui and vi.

The next line contains n integer numbers, the i-th of them corresponds to initi (initi is either 0 or 1). The following line also contains n 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 next cnt lines should contain an integer xi, representing that you pick a node xi.

Examples
Input
10
2 1
3 1
4 2
5 1
6 2
7 5
8 6
9 8
10 5
1 0 1 1 0 1 0 1 0 1
1 0 1 0 0 1 1 1 0 1
Output
2
4
7

题目大意:

给你一个以节点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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值