【ybtoj 高效进阶 2.4】 【Trie树】 最长异或路径
题目
解题思路
先求出根节点到各个节点之间的异或路径,存进s数组
点l到点r之间的异或值即s[l]^s[r]异或后的结果
问题就转变为这题了
代码
#include<iostream>
#include<cstdio>
using namespace std;
struct lzf{
int to,q,next;
}m[300010];
int n,t,u,v,w,tot=1,ans;
int s[3200010],head[3200010],trie[3200010][5];
void add(int x,int y,int q)
{
m[++t].to=y;
m[t].q=q;
m[t].next=head[x];
head[x]=t;
}
void dfs(int dep,int fa)
{
for (int i=head[dep];i;i=m[i].next)
{
if (m[i].to==fa) continue;
s[m[i].to]=s[dep]^m[i].q;
dfs(m[i].to,dep);
}
}
void insert(int x)
{
int p=1;
for (int i=31;i>=0;i--)
{
int c=(x>>i) & 1;
if (!trie[p][c]) trie[p][c]=++tot;
p=trie[p][c];
}
}
int find(int x)
{
int zsans=0,p=1;
for (int i=31;i>=0;i--)
{
int c=((x>>i) & 1) == 1 ? 0 : 1;
if (trie[p][c])
zsans+=int(1<<i);
else c=(x>>i) & 1;
p=trie[p][c];
}
return zsans;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<n;i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w); //构建邻接表
}
dfs(1,0); //求出根节点到各个节点的异或路径
for (int i=1;i<=n;i++) insert(s[i]); //存入字典树
for (int i=1;i<=n;i++)
{
int d=find(s[i]); //匹配答案
ans=max(ans,d);
}
printf("%d\n",ans);
return 0;
}