大体思路还是贪心,是根据树的深度一步一步来的
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=1e5+5;
int n,U,V,W;
int ans;
int head[MAXN],tot;
struct tEdge{
int Next,To;int dis;
void ADD(const int &u,const int &v,const int &w)
{
Next=head[u],To=v;dis=w;
head[u]=tot;
return ;
}
}E[MAXN<<1];//建树
int xv[MAXN];
void DFS(const int &r,const int &fa)
{
for(int i=head[r];i;i=E[i].Next)
{
int v=E[i].To;
if(v==fa) continue;
xv[v]=xv[r]^E[i].dis;
DFS(v,r);
}
return ;
}
#define sigma_size 2
#define max_node MAXN*50
struct tTrieTree{
int child[max_node][sigma_size];
int tot;
void Insert(int x)
{
int p=0,tmp=0;
for(int i=1<<30;i;i>>=1)
{
tmp=(x&i)?1:0;
if(!child[p][tmp]) child[p][tmp]=++tot;
p=child[p][tmp];
}
return ;
}
int get(const int &p1,const int &p2,const int &dep,const bool &op)//在子树p1,p2上找异或和
{
if(dep==31) return 0;
int tmp11=child[p1][0],tmp12=child[p1][1];
int tmp21=child[p2][0],tmp22=child[p2][1];
bool k1=tmp11&&tmp22,k2=tmp12&&tmp21;//k1为true表示p1上有0且p2上有1,那么贪心,在tmp11和tmp22上找异或和;k2同理
int res1=(op?1<<(30-dep):0),debugtmp=0;
if(k1&&k2)//讨论
{
int debugtmp1=get(tmp11,tmp22,dep+1,1);
int debugtmp2=get(tmp12,tmp21,dep+1,1);
debugtmp=res1+max(debugtmp1,debugtmp2);
}
else if(k1) debugtmp=res1+get(tmp11,tmp22,dep+1,1);
else if(k2) debugtmp=res1+get(tmp12,tmp21,dep+1,1);
else if(tmp11) debugtmp=res1+get(tmp11,tmp22,dep+1,0);
else debugtmp=res1+get(tmp12,tmp21,dep+1,0);
return debugtmp;
}
}T;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
// cerr<<(4^11);
cin>>n;
for(int i=1;i<n;++i)
{
cin>>U>>V>>W;
E[++tot].ADD(U,V,W),E[++tot].ADD(V,U,W);
}
DFS(1,0);//建树+预处理异或和
for(int i=1;i<=n;++i) T.Insert(xv[i]);//插入
int a1=0,D=0;
while(true)//寻找深度最小的有两个儿子的节点
{
if(T.child[a1][1]&&T.child[a1][0]) break;
a1=(T.child[a1][1]?T.child[a1][1]:T.child[a1][0]);
++D;//记录深度
}
cout<<T.get(T.child[a1][1],T.child[a1][0],D,1);
return 0;
}