实际上,这题只要任选一个根,将无根树转为有根树,构造val[x]表示从根到x节点的异或和,就变成模板LOJ10050了
为什么这样是对的?
- 异或同一个数偶数次等于啥也没干
异或满足交换律( x xor y=y xor x x x o r y = y x o r x )
所以可以构造“前缀异或”
若(x,y)不在同一条到根的树链上,显然val[x] xor val[y]没问题
- 若(x,y)各自到根的树链有并链,则
(val[x] xor val[z])xor(val[y] xor val[z])
=val[x] xor val[y] xor val[z] xor val[z]
=val[x] xor val[y]
- 若(x,y)在同一条到根的树链上,val[x] xor val[y]=val[y] xor val[x]
然后就好了,复杂度 O(N∗30∗2) O ( N ∗ 30 ∗ 2 )
#include<bits/stdc++.h>
#define gt() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++)
#define __R register
using namespace std;
static char buf[1000000],*p1=buf,*p2=buf;
const int maxn=(1e5)+5,L=31;
int n,Ans,val[maxn],Pow[L+5];
int tot,son[maxn<<1],nxt[maxn<<1],lnk[maxn],w[maxn<<1];
void add_e(int x,int y,int z){son[++tot]=y,w[tot]=z,nxt[tot]=lnk[x],lnk[x]=tot;}
int read(){
int ret=0;char ch=gt();
while(ch<'0'||ch>'9') ch=gt();
while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=gt();
return ret;
}
struct Trie{
int tot,s[maxn*L][3],cnt[maxn*L];
inline void insert(int x){
__R int rot=0;__R bool p;
for(__R int i=L-1;i>=0;i--) rot=s[rot][p=(x>>i)&1]=s[rot][p]?s[rot][p]:++tot;
}
inline void check(int x){
__R int rot1=0,rot2=0,now=0;__R bool p;
for(__R int i=L-1;i>=0;i--){
rot1=s[rot1][p=(x>>i)&1];
if(s[rot2][!p]) now|=Pow[i],rot2=s[rot2][!p];else rot2=s[rot2][p];
if(now+Pow[i]-1<=Ans) return;
}
Ans=now;
}
}T;
void DFS(int x,int fa){for(__R int j=lnk[x];j;j=nxt[j])if(son[j]!=fa) T.insert(val[son[j]]=val[x]^w[j]),DFS(son[j],x);}
int main(){
n=read();
for(__R int i=0;i<L;i++) Pow[i]=1<<i;
for(__R int i=1;i<n;i++){
int x=read(),y=read(),z=read();
add_e(x,y,z),add_e(y,x,z);
}
DFS(1,-1);
for(__R int i=1;i<=n;i++) T.check(val[i]);
printf("%d\n",Ans);
return 0;
}