题目链接
前置知识
-
什么是异或? -----如果二进制下同一位不相同,则为(1),否则为(0)
-
trie树
-
基本位运算
对于同一条边异或两次,相当于没有进行异或,我们将dis[i]表示为从i点到根节点的路径异或和。则问题转化为了求两点的dis异或最大值
我们可以根据dis构建一颗01 trie树(自行百度)
贪心的想,对于一个数X,我们对于dis[i]^x最大,则每次往x相反的值选。
及如果x这一位是1,我们在trie树上往0跑,反之往1跑。这样的一定是最大的。
code
#include<bits/stdc++.h>
#define int ll
#define rg register
#define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
typedef long long ll;
const int N=1000010;
int read(){
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
return f*x;
}
int dis[N],head[N],cnt,tot=1;
struct node {
int to,next,v;
}b[N<<1];
void dfs(int x,int fa){
for(int i=head[x];i;i=b[i].next){
int v=b[i].to;
if(v==fa)
continue;
dis[v]=dis[x]^b[i].v;
dfs(v,x);
}
}
void add(int x,int y,int v){
b[++cnt].to=y;
b[cnt].next=head[x];
b[cnt].v=v;
head[x]=cnt;
}
struct node1 {
int ch[2];
}a[N<<2];
void build(int x){
int u=1;
for(int i=32;i>=0;i--){
int c=(x>>i)&1;
if(!a[u].ch[c])
a[u].ch[c]=++tot;
u=a[u].ch[c];
}
}
int find(int x){
int u=1,ans=0;
for(int i=32;i>=0;i--){
int c=((x>>i)&1)^1;
if(a[u].ch[c])
u=a[u].ch[c],ans+=1<<i;
else
u=a[u].ch[c^1];
}
return ans;
}
main(){
int n=read(),x,y,z,ans=0;
for(int i=1;i<n;i++)
x=read(),y=read(),z=read(),add(x,y,z),add(y,x,z);
dfs(1,0);
for(int i=1;i<=n;i++)
build(dis[i]);
for(int i=1;i<=n;i++)
ans=max(ans,find(dis[i]));
printf("%lld",ans);
return 0;
}