最长异或路径 - 洛谷
题目描述
给定一棵 nn 个点的带权树,结点下标从 11 开始到 nn。寻找树中找两个结点,求最长的异或路径。
异或路径指的是指两个结点之间唯一路径上的所有边权的异或。
输入格式
第一行一个整数 nn,表示点数。
接下来 n-1n−1 行,给出 u,v,wu,v,w ,分别表示树上的 uu 点和 vv 点有连边,边的权值是 ww。
输出格式
一行,一个整数表示答案。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100001;
int tire[N<<5][2];
int sum[N];
struct node{
int to;
int nxt;
int w;
}edge[N<<1];
int head[N];
int cnt,n;
int tot;
void add(int from,int to,int w)
{
edge[cnt].to=to;
edge[cnt].w=w;
edge[cnt].nxt=head[from];
head[from]=cnt++;
}
void dfs(int now,int fa)
{
for(int i=head[now];~i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v!=fa){
sum[v]=sum[now]^edge[i].w;
dfs(v,now);
}
}
}
void build(int x)
{
int p=0;
for(int i=(1<<30);i;i>>=1)
{
bool fl=x&i;
if(!tire[p][fl])tire[p][fl]=++tot;
p=tire[p][fl];
}
}
int query(int x)
{
int p=0;
int ans=0;
for(int i=(1<<30);i;i>>=1)
{
bool fl=x&i;
if(tire[p][!fl]){
ans+=i;
p=tire[p][!fl];
}
else p=tire[p][fl];
}
return ans;
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d",&n);
int a,b,c;
for(int i=0;i<n-1;i++)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
dfs(1,-1);
for(int i=1;i<=n;i++)build(sum[i]);
int ans=0;
for(int i=1;i<=n;i++)ans=max(ans,query(sum[i]));
printf("%d",ans);
return 0;
}