【Ybtoj 第9章例3】最长异或路径【Trie树】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


解题思路

考虑如何求一段路径的异或,我们知道,两个相同的数异或之后的值为0。

s [ i ] s[i] s[i]表示根节点到点 i i i的异或值,则点 l l l到点 r r r之间路径的异或值为 s l s_l sl x o r xor xor s r s_r sr,故,我们可以先预处理出s数组,答案变为 m a x max max s i s_i si x o r xor xor s j s_j sj ( 1 < = i < j < = n ) (1<=i<j<=n) (1<=i<j<=n),这个问题等同于上一题——最大异或对


代码

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

int n,k,s[3200010],trie[3200010][2],h[200010],tot=1,u,v,w,ans;

struct c{
    
    
	int x,next,w;
}a[200010]; 

void add(int x,int y,int w)//建邻接表
{
    
    
	k++;
	a[k].x=y;
	a[k].next=h[x];
	a[k].w=w;
	h[x]=k;
}

void dfs(int x,int fa){
    
    //求出所有的s[i]
	int v;
	for(int i=h[x];i;i=a[i].next)
	{
    
    
		v=a[i].x;
		if(v==fa)continue;
		s[v]=s[x]^a[i].w;
		dfs(v,x);
	}
}

int get(int x){
    
    
	int p=1,ans=0,c;
	for(int i=31;i>=0;i--)
	{
    
    
		if(((x>>i)&1)==1)
			c=0;
		else c=1;
		if(trie[p][c])
			ans+=(1<<i);
		else c=(x>>i)&1;
		p=trie[p][c];
	}
	return ans;
}

void insert(int x){
    
    
	int p=1,c;
	for(int i=31;i>=0;i--)
	{
    
    
		c=(x>>i)&1;
		if(!trie[p][c])
			trie[p][c]=++tot;
		p=trie[p][c];
	}
}

int main(){
    
    
	scanf("%d",&n);
	for(int i=1;i<=n-1;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++)
		ans=max(ans,get(s[i]));
	printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/kejin2019/article/details/115019815