ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

最近公共祖先(LCA)(RMQ)

2022-07-01 13:07:39  阅读:195  来源: 互联网

标签:10000010 RMQ 祖先 dfso st down int LCA


最近公共祖先(LCA)(RMQ)

作为求LCA的常见方法之一,RMQ算法可以以O(nlogn)的复杂度初始化,然后以O(1)的复杂度进行查询。RMQ(Range Minimum/Maximum Query)意为区间最值查询,即查找区间[l,r]中元素的最大/小值。但今天讨论的算法是有关树的,因此我们要想办法把树转换成一个满足我们需求的序列。

欧拉序


如图,这棵树的其中一个欧拉序为1,2,4,2,5,2,1,3,6,3,7,3,1。它其实是对树从根节点开始进行一个dfs,每个节点在进入子树之前记录一次、退出之后记录一次。这样的好处是任意两个节点的最近公共祖先一定是在他们之间,且是他们之间元素中层数最小的那一个。因此,对于每对询问的节点A和B,我们只要找到A和B在欧拉序中第一次出现的位置a和b,则他们的最近公共祖先一定是区间[a,b]中层数最小的元素。
但我们应当如何找到区间[a,b]中层数最小的元素呢?用st表解决。

代码

#include<bits/stdc++.h>
using namespace std;
int n,m,s,x,y,a,b;
vector<int> tmap[10000010];
int dep[10000010];
int dfso[10000010],down=1;
int st[10000010][30];
int numo[10000010]={0};
void dfs(int st,int fa,int d)//dfs一遍,求出层数、欧拉序
{
	if(numo[st]==0)numo[st]=down;
	dep[st]=d;
	dfso[down++]=st;
	for(auto i:tmap[st])
	{
		if(i==fa)continue;
		dfs(i,st,d+1);
		dfso[down++]=st;
	}
}
void st_init()//初始化st表
{
	for(int i=down-1;i>=1;i--)
	{
		st[i][0]=dfso[i];
		for(int j=1;j<20;j++)
		{
			if(i+(1<<(j-1))>(down-1))break;
			st[i][j]=dep[st[i][j-1]]<dep[st[i+(1<<(j-1))][j-1]]?st[i][j-1]:st[i+(1<<(j-1))][j-1];
		}
	}
}
int fnd(int a,int b)//O(1)查找
{
	int l=numo[a],r=numo[b];
	if(l>r)swap(l,r);
	int k=log2(r-l+1);
	return dep[st[l][k]]<dep[st[r-(1<<k)+1][k]]?st[l][k]:st[r-(1<<k)+1][k];
}
int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&x,&y);
		tmap[x].push_back(y);
		tmap[y].push_back(x);
	}
	dfs(s,s,1);
	st_init();
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&a,&b);
		printf("%d\n",fnd(a,b));
	}
	return 0;
}

标签:10000010,RMQ,祖先,dfso,st,down,int,LCA
来源: https://www.cnblogs.com/huled/p/16434205.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有