【ybtoj 高效进阶 2.4】 【Trie树】 最长异或路径

【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;
}  

猜你喜欢

转载自blog.csdn.net/qq_45621109/article/details/115255315