题目链接:P4551 最长异或路径
题意:n个点的一棵树,两点间的距离是路径上所有边权的异或和;
分析:由树的性质可以想到:dis[u][v]=dis[root][u]^dis[root][v],那么就dfs一棵树出来,更新dis[root][i];
每个点dis的二进制01串建一棵trie,然后从高向低,贪心选取高位异或为1的;
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn=5e6+7;
const int mod=1e9+7;
const ll INF=1e18;
int head[maxn],tot=1,dis[maxn],ans;
struct node{int v,w,nxt;} g[maxn];
void add(int u,int v,int w)
{
g[tot]={v,w,head[u]};
head[u]=tot++;
}
struct trie //处理异或
{
int nex[maxn][2],cnt=0;
void insert(int x) //插入字符串
{
int p=0;
for(int i=30;i>=0;i--)
{
int c=((x>>i)&1);
if(!nex[p][c]) nex[p][c]=++cnt;
p=nex[p][c];
}
}
int find(int x) //查找字符串
{
int p=0,res=0;
for(int i=30;i>=0;i--)
{
int c=((x>>i)&1);
if(!nex[p][c^1]) {p=nex[p][c];continue;}
p=nex[p][c^1];res|=(1<<i);
}
ans=max(ans,res);
}
}Trie;
void dfs(int x,int fa)
{
Trie.insert(dis[x]);
Trie.find(dis[x]);//后面的会扫到前面 所以不会漏掉情况
for(int i=head[x];i;i=g[i].nxt)
{
int v=g[i].v,w=g[i].w;
if(v==fa) continue;
dis[v]=dis[x]^w;
dfs(v,x);
}
}
void rua()
{
int n;scanf("%d",&n);
for(int i=1;i<n;i++)
{
int x,y,z;scanf("%d%d%d",&x,&y,&z);
add(x,y,z);add(y,x,z);
}
dfs(1,0);
printf("%d\n",ans);
}
int main()
{
rua();
return 0;
}