发现题面很类似这样一个经典问题:
给出一堆数字,再给你一个数,找到那堆数中与这个数异或最大的
这个问题很经典了,直接建立字典树
对于每个数,二进制分解,然后把二进制从高位到低位插入到字典树上
形成一个深度为的字典树,异或最大值就不停的贪心选择走
还是走
即可
但是树上路径没那么简单了,不再是简单的两数异或......
但是如果处理一个数组,表示根到自己的异或值
那么和
的路径异或值不就是
吗
因为他们的部分异或了两次,消掉了
这样一来,转化为把插入字典树了
#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;
} 
京公网安备 11010502036488号