解题思路
考虑如何求一段路径的异或,我们知道,两个相同的数异或之后的值为0。
设 s [ i ] s[i] s[i]表示根节点到点 i i i的异或值,则点 l l l到点 r r r之间路径的异或值为 s l s_l sl x o r xor xor s r s_r sr,故,我们可以先预处理出s数组,答案变为 m a x max max s i s_i si x o r xor xor s j s_j sj ( 1 < = i < j < = n ) (1<=i<j<=n) (1<=i<j<=n),这个问题等同于上一题——最大异或对
代码
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,k,s[3200010],trie[3200010][2],h[200010],tot=1,u,v,w,ans;
struct c{
int x,next,w;
}a[200010];
void add(int x,int y,int w)//建邻接表
{
k++;
a[k].x=y;
a[k].next=h[x];
a[k].w=w;
h[x]=k;
}
void dfs(int x,int fa){//求出所有的s[i]
int v;
for(int i=h[x];i;i=a[i].next)
{
v=a[i].x;
if(v==fa)continue;
s[v]=s[x]^a[i].w;
dfs(v,x);
}
}
int get(int x){
int p=1,ans=0,c;
for(int i=31;i>=0;i--)
{
if(((x>>i)&1)==1)
c=0;
else c=1;
if(trie[p][c])
ans+=(1<<i);
else c=(x>>i)&1;
p=trie[p][c];
}
return ans;
}
void insert(int x){
int p=1,c;
for(int i=31;i>=0;i--)
{
c=(x>>i)&1;
if(!trie[p][c])
trie[p][c]=++tot;
p=trie[p][c];
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
dfs(1,0);
//后面的就跟上一题(最大异或对)一样了
for(int i=1;i<=n;i++)
insert(s[i]);
for(int i=1;i<=n;i++)
ans=max(ans,get(s[i]));
printf("%d",ans);
}