求助LCA(倍增法)
  • 板块学术版
  • 楼主Star_Whale
  • 当前回复3
  • 已保存回复3
  • 发布时间2023/7/16 11:04
  • 上次更新2023/11/3 09:34:46
查看原帖
求助LCA(倍增法)
571445
Star_Whale楼主2023/7/16 11:04
#include<bits/stdc++.h>
using namespace std;
struct Edge
{
	int to;
	int next;
}edge[500005*2];
int head[500005],grand[500005][21],depth[500005],lg[500001];
int cnt,n,m,s;
int insert_(int x,int y)
{
	edge[++cnt].to=y;
	edge[cnt].next=head[x];
	head[x]=cnt;
}
 
void dfs(int now,int fa)
{
	depth[now]=depth[fa]+1;
	grand[now][0]=fa;
	for(int i=1;i<=lg[depth[now]];i++)
	//for(int i=1;(1<<i)<=depth[now];i++)
		grand[now][i]=grand[grand[now][i-1]][i-1];
		//爸爸的爸爸叫爷爷~~~ 
	for(int i=head[now];i;i=edge[i].next)
	//遍历和当前结点相连的所有的边(按输入的倒序),最后一条边的 edge[i].next==0
	{
		//cout<<"第"<<i<<"条边,指向" <<edge[i].to<<endl; 
		if(edge[i].to!=fa)
			dfs(edge[i].to,now);
	}
}
 
int LCA(int a,int b)
{
	if(depth[a]<depth[b])
		swap(a,b);
	while(depth[a]>depth[b])
		a=grand[a][lg[depth[a]-depth[b]]-1];
	//倍增法逼近,e.g:depth[a]-depth[b]==14
	//lg[depth[a]-depth[b]]-1==3,a上升8个深度,depth[a]-depth[b]==6; 
	//lg[depth[a]-depth[b]]-1==2,a上升4个深度,depth[a]-depth[b]==2; 
	//lg[depth[a]-depth[b]]-1==1,a上升2个深度,depth[a]-depth[b]==0; 
	if(a==b) return a;//a和b的LCA就是a 
	for(int k=lg[depth[a]]-1;k>=0;k--)
		if(grand[a][k]!=grand[b][k])
			a=grand[a][k],b=grand[b][k];
	//从远古祖先(注意不要越界)中逐渐向最近的试探 
	// e.g:depth[a]==14,depth[LCA]==7;
	// k=lg[depth[a]]-1,k==3;grand[a][k]==grand[b][k];continue;
	//k==2,grand[a][k]!=grand[b][k],a,b一起向上4个深度;
	//k==1,grand[a][k]!=grand[b][k],a,b一起向上2个深度;
	//k==0,grand[a][k]!=grand[b][k],a,b一起向上1个深度; 
	//一共向上4+2+1==7个深度,找到LCA 
	return grand[a][0];
}
 
int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1;i<=n-1;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		insert_(x,y);
		insert_(x,y);
	}
	for(int i=1;i<=n;i++)
		lg[i]=lg[i-1]+((1<<lg[i-1])==i);
	dfs(s,0); 
	while(m--)
	{
		int qx,qy;
		scanf("%d%d",&qx,&qy);
		printf("%d\n",LCA(qx,qy));
	}
	return 0;
}

grand数组和depth数组的意思???

2023/7/16 11:04
加载中...