P4551 最长异或路径
传送锚点
异或的性质:
- 一个数异或它本身的值为 \(0\)
- 任何数异或 \(0\) 的值为原数的值
思路:
- 利用这一性质, 我们可以把路径的异或和转化为路径两端点到跟的异或和的异或
- 于是,我们利用 \(01\)Trie , 把原数上每一个数到根的异或和都建一棵 Trie
- 这样, 问题就转化为了在这新数中寻找最大异或对
- 跑一边 \(01\)Trie 即可
Code:
/*************************************************************************
> File Name: p4551.cpp
> Author: Typedef
> Mail: 1815979752@qq.com
> Created Time: 2021年07月22日 星期四 21时56分26秒
> Blog: https://www.cnblogs.com/Illyasviel
************************************************************************/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+7;
struct Trie{
int s[2];
}tr[N*43];
int n;
int sum[N];
int h[N],e[N<<1],ne[N<<1];
template<class T>void qread(T &x){
x=0;bool f=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
if(f) x=-x;
}
int idx=0;
int val[N<<1];
void add(int a,int b,int c){
e[idx]=b;
val[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
void dfs(int u,int father){
for(int i=h[u];~i;i=ne[i]){
int v=e[i];
if(v==father) continue;
sum[v]=sum[u]^val[i];
dfs(v,u);
}
}
int cnt=0;
void insert(int val,int pos){
for(int i=(1<<30);i;i>>=1){
bool p=val&i;
if(!tr[pos].s[p]) tr[pos].s[p]=++cnt;
pos=tr[pos].s[p];
}
}
int query(int val,int pos){
int res=0;
for(int i=(1<<30);i;i>>=1){
bool p=val&i;
if(tr[pos].s[p^1]) res+=i,pos=tr[pos].s[p^1];
else pos=tr[pos].s[p];
}
return res;
}
int main(){
memset(h,-1,sizeof(h));
qread(n);
for(int i=1;i<n;i++){
int x,y,z;
qread(x),qread(y),qread(z);
add(x,y,z);
add(y,x,z);
}
dfs(1,-1);
int ans=0;
for(int i=1;i<=n;i++)
insert(sum[i],0);
for(int i=1;i<=n;i++) ans=max(ans,query(sum[i],0));
printf("%d\n",ans);
return 0;
}