Xor Path
Xor Path
https://ac.nowcoder.com/acm/problem/20857
题意:
有一棵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; }