P4551 最长异或路径 题解

点点圈 提交于 2019-12-18 14:50:19

P4551 最长异或路径

Trie-字典树-图论

给出一个无根树,每条边有边权,求一条路径,使得这条路径上的边权异或和最大

下面一些关于异或最短路和证明:

与普通最短路不一样的是,这里最短路的距离求的是异或和,而这里的关键就是异或的重要性质:逆反性

首先,随便选一个点ss当起点,跑一边最短路,求出dis数组,dis[x]dis[x]表示点xx到起点的最短路长度。
当询问点xx到点yy的最短路时,分两种情况:

  1. xx到点yy的最短路径经过点ss,那xxyy的最短路就是dis[x]^dis[y]

  2. xx到点yy的最短路径不经过点ss,如下图:
    image.png

xxyy的最短路为ccdis[x]=adis[x]=a的话,可证明出dis[y]=a ^ c,而这样的话dis[x] ^ dis[y] = a ^ c ^ a = c
所以,点xx到点yy的最短路还是dis[x]^dis[y]

上面证明我的博客题解 P5651 【基础最短路练习题】,那题也是求异或和最短路

找出异或的性质后,第一个想到的肯定是O(n2)O(n^2)的枚举起点和终点。而这个方法,可以转化成对于每一个点xx,求树中离他最远的点路径长度

我们可以把第二维用Trie来优化
首先,随便找一个点为根,求出所有点距根节点的距离disdis,并把每个点的disdis化为二进制存入TrieTrie

然后,枚举每个点的时候,在TrieTrie中找出:二进制位与当前点尽可能多的不同,并求出最大值

最后将所有输出最大值

#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
const int Maxn=100000+20,inf=0x3f3f3f3f;
struct edge{
	int v,len;
	edge(int x,int y)
	{
		v=x,len=y;
	}
};
vector <edge> e[Maxn];
int dis[Maxn],g[3100000+233][2];
int n,ans,idcnt=1;
inline int read()
{
	int s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return s*w;
}
inline void add(int x)
{
	int cur=1;
	for(int i=(1<<30);i;i>>=1)
	{
		bool y=(x & i);
		//printf("%d %d %d\n",++cnt,cur,y);
		if(!g[cur][y])
		{
			g[cur][y]=++idcnt;
			//printf("%d %d %d\n",cur,idcnt,y);
		}
		cur=g[cur][y];
	}
}
void dfs(int x,int fa)
{
	for(int i=0;i<e[x].size();++i)
	{
		int y=e[x][i].v;
		if(y==fa)continue;
		dis[y]=dis[x]^e[x][i].len;
		dfs(y,x);
	}
}
int query(int x)
{
	int cur=1,ret=0;
	for(int i=(1<<30);i;i>>=1)
	{
		bool opt=(x & i);
		if(g[cur][opt^1])
		{
			ret+=i;
			cur=g[cur][opt^1];
		}
		else cur=g[cur][opt];
	}
	return ret;
}
int main()
{
	//freopen("in.txt","r",stdin);
	n=read();
	for(int i=1;i<n;++i)
	{
		int x=read(),y=read(),c=read();
		e[x].push_back(edge(y,c));
		e[y].push_back(edge(x,c));
	}
	dis[1]=0;
	dfs(1,0);
	for(int i=1;i<=n;++i)
	add(dis[i]);
	
	for(int i=1;i<=n;++i)
	ans=max(ans,query(dis[i]));
	printf("%d\n",ans);
	return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!