#include<bits/stdc++.h>
using namespace std ;
#define endl "\n"
#define ll long long
const ll N=5e5+11;
struct node{ ll v,w,next; }e[4*N];
ll head[N],Cnt=0;
void add(ll x,ll y,ll z)
{
Cnt++;
e[Cnt].v=y;
e[Cnt].w=z;
e[Cnt].next=head[x];
head[x]=Cnt;
}
ll deep[N],fa[N][30];
void bfs(ll root)
{
queue<ll>q;
q.push(root);deep[root]=1;
while(!q.empty()){
ll u=q.front();q.pop();
for(ll i=head[u];i;i=e[i].next){
ll v=e[i].v;
if(deep[v]) continue;
deep[v]=deep[u]+1;
fa[v][0]=u; //v的上一个节点是u
for(ll j=1;j<=22;j++){
fa[v][j]=fa[fa[v][j-1]][j-1]; //相当于 2^j = 2^(j-1) * 2^(j-1)
}
q.push(v);
}
}
}
ll Lca(ll x,ll y)
{
if(deep[x]>deep[y]) swap(x,y); //让y的深度大于x
for(ll i=22;i>=0;i--) //让y ,x的深度一样
if(deep[fa[y][i]]>=deep[x]) y=fa[y][i];
if(x==y) return x;
for(ll i=22;i>=0;i--) //(x,y)祖先不一样是才往上跳
if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
// 因为(x,y)祖先不一样是才往上跳,最后(x,y)是在Lca的下一层
return fa[x][0];
}
void solve()
{
ll n,m,s;
cin>>n>>m>>s;
for(ll i=1;i<=n;i++) head[i]=0,deep[i]=0;//初始化
//读入一棵树
Cnt=1;
for(ll i=1;i<=n-1;i++){
ll x,y;
cin>>x>>y;
add(x,y,1);add(y,x,1);
}
bfs(s);//s是树根,初始化 fa[][] 和 deep[]
while(m--){
ll x,y;
cin>>x>>y;
cout<<Lca(x,y)<<endl;
}
}
int main()
{
ios::sync_with_stdio(0); cin.tie(0);cout.tie(0);
ll Test=1;
//cin>>Test;
while(Test--){
solve();
}
return 0;
}
P3379 【模板】最近公共祖先(LCA)倍增法
于 2024-07-18 04:02:12 首次发布