倍增lca

// Problem: P3379 【模板】最近公共祖先(LCA)
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3379
// Memory Limit: 512 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
const int mn=500005;
int n,m,s;
int d[mn],f[mn][21];//depth,f[i][j]表示i向上跳pow(2,j)次到达的点
vector<int> v[mn];
void dfs(int x,int y)
{
	f[x][0]=y;//跳一次就是父亲
	d[x]=d[y]+1;
	for(int i=1;i<=20;i++)
	{
		f[x][i]=f[f[x][i-1]][i-1];//跳pow(2,j-1)次到的点跳pow(2,j-1)次就是跳了pow(2,j)次
	}
	for(int i=0;i<v[x].size();i++)
	{
		if(v[x][i]!=y)
		{
			dfs(v[x][i],x);
		}
	}
}
int lca(int x,int y)
{
	if(d[x]<d[y])
	{
		swap(x,y);
	}
	int a=d[x]-d[y];
	for(int i=0;i<=20;i++)
	{
		if((a>>i)&1)x=f[x][i];//让两点在同一深度
	}
	if(x==y)return x;
	for(int i=20;i>=0;i--)
	{
		if(f[x][i]!=f[y][i])//不相等说明可以跳
		{
			x=f[x][i];
			y=f[y][i];
		}
	}
	return f[x][0];
}
int main()
{
	cin>>n>>m>>s;
	int x,y;
	for(int i=1;i<n;i++)
	{
		cin>>x>>y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	dfs(s,0);
	while(m--)
	{
		cin>>x>>y;
		cout<<lca(x,y)<<'\n';
	}
	return 0;
}

posted @ 2025-02-08 19:57  ikusiad  阅读(31)  评论(0)    收藏  举报