题目
参考博客 参考代码

#include<bits/stdc++.h>
using namespace std;
int const M=5e5+7;
int const N=5e5+7;
int n,m,s;
struct node{
	int a,next,len;
}e[M<<1];
int cnt,head[N];
void add(int x,int y,int len){
	e[++cnt].a =y;
	e[cnt].len =len;
	e[cnt].next =head[x];
	head[x]=cnt;
}
int lg[N]; //lg[i]表示深度为i的节点可以向上跳的次数  // 
int fa[N][37];  //fa[i][j]表示第i个节点的 2^j的祖先是谁 
int dh[N],vis[N];  //dh[i]表示i节点的深度
void dfs(int s,int fath){ //找出每个节点的深度
	fa[s][0]=fath; //fath在这一步操作比较方便 
	dh[s]=dh[fath]+1; 
	for(int i=1;i<=lg[ dh[s] ];++i){
		fa[s][i]=fa[ fa[s][i-1] ][i-1];
	}
	for(int i=head[s];i!=-1;i=e[i].next){
		if(e[i].a==fath) continue;
		dfs(e[i].a,s);
	}
}
int lca(int a,int b){
	if(dh[a]<dh[b]) swap(a,b);
	while(dh[a]>dh[b]) a=fa[a][ lg[dh[a]-dh[b]] -1 ];  //这里跳满(即跳最大值)的话,dh[a]有可能小于dh[b],所以这里lg要减一,这样循环之后,它们深度才能一样 
	if(a==b) return a;
	for(int k=lg[dh[a]];k>=0;--k){ 
		if(fa[a][k]!=fa[b][k]) a=fa[a][k],b=fa[b][k];
	} 
	return fa[a][0];
}
int main(){
	cin >> n >> m >> s;
	memset(head,-1,sizeof head);
	memset(e,-1,sizeof e);
	for(int i=1;i<=n-1;++i){
		int a,b;cin >> a >> b;
		add(a,b,1);add(b,a,1);
	}
	for(int i=1;i<=n;++i){
		lg[i]=lg[i-1]+((1<<lg[i-1])==i);   //(1<<lg[i-1])==i表示i是否是2^k次方,是就加一次   
	} 									//lg[6]=3 深度为6的点可以按二进制即倍增的方式跳3次,最大跳8(即2^3),所有点最大的那一次都是跳到0
	dfs(s,0);      //0号节点为所有节点的祖先(为了方便操作) 
	while(m--){
		int a,b;
		cin >> a >> b;
		cout << lca(a,b) << "\n";
	}
	return 0;
}