题意:
有一棵n个节点的树,树的每一个节点有一个权值,定义path(i,j)表示 i 到 j 的最短路径上,所有点的点权异或和。求所有path(i,j)的异或和。
思路:
我们可以统计一个点被计算了多少次来求解,一个节点x,以x为终点的path有(n-1)条,然后包括它的路径与它的子树有关,一棵子树的节点到另一颗子树的节点路径包括x,节点数为偶数的不考虑,计算为奇数节点的个数,因为奇数 * 奇数才等于奇数。然后判断奇子树二二组合的数目,然后就将这值与n-1加起来是否为奇数,为奇数则ans异或x节点的权值,否则不管。
代码:
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll inf=998244353;
vector<int> g[500005];
ll a[500005];
ll ans=0, n;
int dfs(int v,int f)
{
ll p=1, ji=0;
for(int i=0;i<g[v].size();i++)
{
if(g[v][i]!=f)
{
int k=dfs(g[v][i],v);
if(k%2==1)
{
ji++;
}
p=p+k;
}
}
if((n-p)%2==1)
{
ji++;
}
ji--;
if(ji%4>=1&&ji%4<=2)
{
ji=1;
}
else
{
ji=0;
}
ans=ans^(a[v]*((n-1+ji)%2));
return p;
}
int main()
{
scanf("%lld",&n);
for(int i=1;i<n;i++)
{
int u, v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
dfs(1,-1);
cout << ans << endl;
return 0;
}

京公网安备 11010502036488号