题目描述
MT神牛非常喜欢出Xor的题,在WC2011的时候,MT神牛出了一道非常经典的Xor最大路径题。
Bird向MT神牛学习,思考了许多关于Xor路径的问题,有一天,Bird想到了一个问题,给出一个序列,求这个序列的连续子序列的Xor值最大。
如1 3 4 8,最大的Xor子序列当然是3 xor 4 xor 8=15了。
Bird实在太强大了,这个问题怎么能难住他呢?于是Bird又开始思考了,如果是一颗树呢,如何求出这棵带边权的树的一条最大Xor路径呢?但是谁都知道Bird实在太强大了,马上想到了解决这个问题的高效算法,但是Bird总是不愿去机房写代码,于是他把这个easy的问题,交给了你,希望你能尽快帮他写完代码。
题目大意
求树上异或和的最大值。
数据范围
【数据规模】
对于40%的数据,数据退化为一条链
除上述的40%的数据外,还有10%的数据N<=1000
100%的数据满足2 <= n <= 100000,1 < a,b <= N,C <= 2^31-1
样例输入
4
1 2 3
1 3 4
1 4 7
样例输出
7
解题思路
其实树上的异或和最大值和数列上的最大值并没有什么区别。设f[x]为从根到x节点的异或和,x到y的异或和等于f[x]^f[y],因为x,y的lca部分的异或和正好抵消掉了。数列上的异或和最大值就是建一棵Trie树,枚举每个数在Trie树上找。
其实代码也挺短的qwq
代码
#include <bits/stdc++.h>
#define Maxn 100005
using namespace std;
inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
int h[Maxn],f[Maxn],cnt=0;
struct node{int to,next,v;}e[Maxn*2];
void AddEdge(int x,int y,int v){e[++cnt]=(node){y,h[x],v};h[x]=cnt;}
struct trie{int son[2];}Trie[Maxn*32];
void Insert(int x){
int p=0;
for(int i=31;~i;i--){
bool t=x&(1<<i);
if(!Trie[p].son[t])Trie[p].son[t]=++cnt;
p=Trie[p].son[t];
}
}
int Ask(int x){
int ret=0,p=0;
for(int i=31;~i;i--){
bool t=x&(1<<i);
if(Trie[p].son[!t]){
p=Trie[p].son[!t];
ret+=1<<i;
}else p=Trie[p].son[t];
}
return ret;
}
void dfs(int x,int L,int S){
f[x]=S;
for(int p=h[x];p;p=e[p].next){
int y=e[p].to;
if(y==L)continue;
Insert(S^e[p].v);
dfs(y,x,S^e[p].v);
}
}
int main(){
memset(Trie,0,sizeof(Trie));
int n=Getint(),Ans=0;
for(int i=1;i<n;i++){
int x=Getint(),y=Getint(),v=Getint();
AddEdge(x,y,v);
AddEdge(y,x,v);
}
cnt=0;
dfs(1,0,0);
for(int i=1;i<=n;i++)Ans=max(Ans,Ask(f[i]));
cout<<Ans;
return 0;
}