发现题面很类似这样一个经典问题:

给出一堆数字,再给你一个数,找到那堆数中与这个数异或最大的

这个问题很经典了,直接建立字典树

对于每个数,二进制分解,然后把二进制从高位到低位插入到字典树上

形成一个深度为的字典树,异或最大值就不停的贪心选择走还是走即可

但是树上路径没那么简单了,不再是简单的两数异或......

但是如果处理一个数组,表示根到自己的异或值

那么的路径异或值不就是

因为他们的部分异或了两次,消掉了

这样一来,转化为把插入字典树了

#include <bits/stdc++.h>
using namespace std;
const int maxn=8e6+10;
int n;
struct edge{
    int to,nxt,w;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int w){
    d[++cnt]=(edge){v,head[u],w},head[u]=cnt;
}
int dis[maxn];
void dfs(int u,int fa)
{
    for(int i=head[u];i;i=d[i].nxt )
    {
        int v=d[i].to;
        if( v==fa )    continue;
        dis[v]=dis[u]^d[i].w;
        dfs(v,u);
    }
}
int zi[maxn][3],tot;
void insert(int x)
{
    int now=0;
    for(int i=30;i>=0;i--)
    {
        int k=0;
        if( x&(1<<i) )    k=1;
        if( !zi[now][k] )    zi[now][k]=++tot;
        now=zi[now][k];
    }
}
int ask(int x)
{
    int ans=0,now=0;
    for(int i=30;i>=0;i--)
    {
        int k=1;
        if( x&(1<<i) )    k=0;
        if( zi[now][k] )    ans+=(1<<i),now=zi[now][k];
        else    now=zi[now][k^1];
    }
    return ans;
}
int main()
{
    cin >> n;
    for(int i=1;i<n;i++)
    {
        int l,r,w; cin >> l >> r >> w;
        add(l,r,w); add(r,l,w);
    }
    dfs(1,0);
    int ans=0;
    for(int i=1;i<=n;i++)    insert(dis[i]);
    for(int i=1;i<=n;i++)    ans=max(ans,ask(dis[i]) );
    cout << ans;
}