首先说一下题意。

这题就是给你一棵树,求树上所有路径中异或和最大的。

一个前置小芝士01trie树
不会的童鞋自行百度一下(

好了,分析一下本题

我们对于每一个数到根节点的异或和进行建01trie树。
我们知道一个数,如果它两次异或同一个数,那么它是不会变的。
所以i-j的路径上的异或和,就可以表示成根到i的异或和异或上根到j的异或和。
我们就以一个点为根,预处理出根到其他所有节点的路径异或和。
那我们就可以贪心的选取,因为当前位的权值是大于后面所有位的权值之和的。如(1000)=(8)>(0111)=(7)。
所以我们每一位贪心的选取异或后为1的点,否则沿原路向下走。

#include<bits/stdc++.h>
const int N=1e6+5,INF=0x3f3f3f3f;
using namespace std;

inline int read()
{
    register int x=0,f=1;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();
    return x*f;
}

int head[N],sum[N];
int cnt=-1,tot,n;
struct node
{
    int v,w,next_;
}e[N<<1];
struct trie
{
    int son[2];
}t[N];

void add(int u,int v,int w)
{
    e[++cnt].next_=head[u];
    e[cnt].v=v;
    e[cnt].w=w;
    head[u]=cnt;
}

void dfs(int x,int fa)
{
    for(int i=head[x];~i;i=e[i].next_)
    {
        int v=e[i].v;
        int w=e[i].w;
        if(v!=fa)
        {
            sum[v]=sum[x]^w;
            dfs(v,x);
        }
    }
}

void build(int val,int x)
{
    for(int i=(1<<30);i;i>>=1)
    {
        bool c=val&i;
        if(!t[x].son[c])
            t[x].son[c]=++tot;
        x=t[x].son[c];
    }
}

int query(int val,int x)
{
    int ans=0;
    for(int i=(1<<30);i;i>>=1)
    {
        bool c=val&i;
        if(t[x].son[!c])
        {
            ans+=i;
            x=t[x].son[!c];
        }
        else x=t[x].son[c];
    }
    return ans;
}

int main()
{
    memset(head,-1,sizeof(head));
    n=read();
    for(int i=1;i<n;++i)
    {
        int u,v,w;
        u=read();v=read();w=read();
        add(u,v,w);add(v,u,w);
    }
    dfs(1,-1);
    for(int i=1;i<=n;++i) build(sum[i],0);
    int ans=0;
    for(int i=1;i<=n;++i)
        ans=max(ans,query(sum[i],0));
    printf("%d\n",ans);
}