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