题解:
首先我们知道,一个点肯定不可能只出现一次的,他会出现好多次,但是根据二进制
a xor a =0
a xor a xor a =a
所以我们发现当某个点出现的次数为偶数次时,这个点相当于没有出现过,奇数次时,答案异或一下这个点的权值即可。
没有见过这种题的建议先看
求树上任意两点之间距离之和的平均值这个典型题
下面我们借用巨雨的分类方法做这个题
1.x作为一条路径的顶点时,它会被经过n-1次
对应代码:

int ans=n-1;

2.从x的子树内连到子树外,这样的话,子树每一个点都会与树外面每一个点相连
树内的每一点 size[u]-1
树外的点 n-size[u]
所以答案是:树内的每一点 × 树外的点 = (size[u]-1) × (n-size[u])
对应代码:

ans+=(isize[root]-1)*(n-isize[root]);

3.从x的一个子树连到另外一个子树(这样才能经过它)
图片说明
因为我们在递归过程中进行计算,所以算出来的结果没有重复。
举个栗子:
根节点连接着三颗子树
首先你需要遍历完一棵后回溯,由于另外两颗没有遍历过,所以目前来说根节点大小就是 遍历过的子树+1,根据公式计算,发现是0,因为你当前只有一棵子树。
当你遍历完第二棵子树时,你的根节点大小是 第一颗子树+第二棵子树+1,再次计算你发现,计算了1 2两棵子树之间的结果。
当你遍历完第三棵子树时,你的根节点大小是 第一颗子树+第二棵子树+第三棵子树+1,再次计算你发现,计算了1 3和2 3这些子树之间的结果。
所以不存在重复。
对应代码:

ans+=isize[v]*(isize[root]-isize[v]-1);

然后再根据我们之前对二进制的分析进行计算即可。

代码:

/*Keep on going Never give up*/
#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <queue>
#include <string>
const int maxn = 1e6+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1e9+7;
using namespace std;
struct node{
    int to,next;
}edge[maxn];
int head[maxn];
int cnt=1,n;
void add(int u,int v){
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
int isize[maxn],xo[maxn],res;

void dfs(int root,int fa){
    isize[root]=1;
    int ans=n-1;
    for(int i=head[root]; i ;i=edge[i].next){
        int v=edge[i].to;
        if(fa==v) continue;
        dfs(v,root);
        isize[root]+=isize[v];
        ans+=isize[v]*(isize[root]-isize[v]-1);
    }
    ans+=(isize[root]-1)*(n-isize[root]);
    if(ans&1) res^=xo[root];
}

int main(){
    cin>>n;
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    for(int i=1;i<=n;i++) scanf("%d",&xo[i]);
    dfs(1,0);
    cout<<res<<endl;
    return 0;
}