首先说一下题意。
这题就是给你一棵树,求树上所有路径中异或和最大的。
一个前置小芝士: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); }