P3379 【模板】最近公共祖先(LCA) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
int n,m,q;
vector<int> v[maxn];//存树遍历求深度
int d[maxn];//深度
int s[maxn][32];//倍增数组
void dfs(int x,int y)//x是当前遍历到的点,y是父节点
{
d[x]=d[y]+1;
s[x][0]=y;//初始化
//cout<<x<<" "<<d[x]<<endl;
for(int j=1;(1<<j)<=d[x];j++)
{
s[x][j]=s[s[x][j-1]][j-1];
}
for(int i=0;i<v[x].size();i++)
{
if(d[v[x][i]]==0)
{
dfs(v[x][i],x);
}
}
return;
}
int getlca(int x,int y)
{
if(d[x]<d[y]) swap(x,y);
for(int i=20;i>=0;i--)
{
if(s[x][i]!=0&&d[s[x][i]]>=d[y])
{
x=s[x][i];
}
}
if(x==y) return x;
for(int i=20;i>=0;i--)
{
if(s[x][i]!=0&&s[y][i]!=0&&s[x][i]!=s[y][i])
{
x=s[x][i];
y=s[y][i];
}
}
return s[x][0];
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m>>q;
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
v[x].push_back(y);//双向图
v[y].push_back(x);
}
dfs(q,0);//求深度
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
cout<<getlca(x,y)<<endl;
}
return 0;
}