n个节点,m个询问,root为根节点,fa[i][j]表示i的第2j个祖先
#include<bits/stdc++.h>
using namespace std;
const int P=30;
//vector son[500001];
//若清楚每条边哪个是父节点那个是子节点,可以用vector,son[i]表示以i为父节点的子节点;
int n,m,deep[500001],fa[500001][30]={0},root,jump[500005],num=0;
bool judge[500005]={0};
struct nob{
int sta,ed,jump;
}a[1000005];
//邻接表存储边
void add(int sta,int ed){
num++;
a[num].sta=sta;
a[num].ed=ed;
a[num].jump=jump[sta];
jump[sta]=num;
}
void dfs(int pos){
judge[pos]=1;
for (int i=jump[pos]; i>0; i=a[i].jump){
if (judge[a[i].ed]) continue;
deep[a[i].ed]=deep[pos]+1;
fa[a[i].ed][0]=pos;
dfs(a[i].ed);
}
}
void beizeng(){
for (int i=1; i<P; i++){
for (int l=1; l<=n; l++){
fa[l][i]=fa[fa[l][i-1]][i-1];
}
}
}
int LCA(int x,int y){
if (deep[y]>deep[x])
swap(x,y);
int s=deep[x]-deep[y];
for (int i=0; i<P; i++)
if ((1<<i)&s)
x=fa[x][i];
//将深度转为二进制,用倍增来跳
if (x==y) return x;
for (int i=P-1; i>=0; i--){
if (fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];
}
int main(){
scanf("%d%d%d",&n,&m,&root);
//若没有说明根节点的话,那么fa[i][0]==0的为根节点
for (int i=1,x,y; i<n; i++){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
deep[root]=1;
dfs(root);
beizeng();
for (int i=1,x,y; i<=m; i++){
scanf("%d%d",&x,&y);
printf("%d
",LCA(x,y));
}
return 0;
}