链接:https://ac.nowcoder.com/acm/contest/272/B
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
给定一棵n个点的树,每个点有权值AiAi。定义path(i,j)path(i,j)表示 ii 到 jj 的最短路径上,所有点的点权异或和。
对于i=1∼n−1, j=i+1∼ni=1∼n−1, j=i+1∼n,求所有path(i,j)path(i,j)的异或和。
输入描述:
第一行一个整数n。
接下来n-1行,每行2个整数u,v,表示u,v之间有一条边。
第n+1行有n个整数,表示每个点的权值AiAi。
输出描述:
输出一个整数,表示所有path(i,j)path(i,j)的异或和,其中i=1∼n−1, j=i+1∼ni=1∼n−1, j=i+1∼n。
示例1
输入
4 1 2 1 3 1 4 1 2 3 4
输出
5
说明
path(1,2)=A1 xor A2=3path(1,3)=A1 xor A3=2path(1,4)=A1 xor A4=5path(2,3)=A2 xor A1 xor A3=0path(2,4)=A2 xor A1 xor A4=7path(3,4)=A3 xor A1 xor A4=6path(1,2)=A1 xor A2=3path(1,3)=A1 xor A3=2path(1,4)=A1 xor A4=5path(2,3)=A2 xor A1 xor A3=0path(2,4)=A2 xor A1 xor A4=7path(3,4)=A3 xor A1 xor A4=6
再将这6个数异或起来就可以得到答案5了。
备注:
1≤n≤5×105,0≤Ai≤1091≤n≤5×105,0≤Ai≤109。
题解:首先,这是一棵树,涉及异或,应该想到很多节点值会被异或多次,其中,同一个值异或偶数次的话,其贡献就为0,奇数次的话,只需要ans和其异或一下,那么问题来了,如何知道每一个节点值会被重复用到多次呢?
这里,我们可以对所有点单独考虑:
- 对某一个节点而言,它需要和除它以外的所有点连接,即n-1次
- 对某一个节点而言,它的子树之间可以相互连接
- 对某一个节点而言,它的所有子树节点可以通过该点和其它点连接
最终,问题可以转化为求所有节点的子树节点数目,时间复杂度应该是O(n)的,采用dfs,遍历一遍,详见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<queue>
#include<stack>
#define LL long long
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384
using namespace std;
const int maxn=1000005;
LL n;
LL val[maxn],head[maxn],cnt;
LL ans;
LL sum[maxn];//用来记录一个节点下的所有节点数量
bool book[maxn];
struct node
{
LL u,v,nxt;
}edge[maxn];
void init()
{
for(int i=0;i<maxn;i++)
{
head[i]=-1;
sum[i]=1;
}
cnt=0;ans=0;
memset(book,false,sizeof(book));
}
void addedge(int u,int v)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].nxt=head[u];
head[u]=cnt++;
}
void dfs(int rt)
{
LL num=0;
for(int i=head[rt];i!=-1;i=edge[i].nxt)
{
int v=edge[i].v;
if(book[v]==true)
continue;
book[v]=true;
dfs(v);
num+=(sum[rt]-1)*sum[v];
sum[rt]+=sum[v];
}
num+=n-1+(sum[rt]-1)*(n-sum[rt]);
if(num&1)
ans^=val[rt];
}
int main()
{
cin>>n;
init();
for(int i=0;i<n-1;i++)
{
LL a,b;
cin>>a>>b;
addedge(a,b);
addedge(b,a);
}
for(int i=1;i<=n;i++)
cin>>val[i];
book[1]=true;
dfs(1);
cout << ans << endl;
return 0;
}