#include <cstdio>
#include <iostream>
using namespace std;
#define maxn 500010
struct node{
int nex;
int to;
}edge[2 * maxn];
int father[maxn][35];//表示向上的第(1 << i)个父节点
int depth[maxn];
int lg[30];//常数优化,储存(1 << i)的值
int head[maxn], tot;//链式前向星存图
int n, m, s;
void get_lg(){
lg[0] = 1;
for(int i = 1; i <= 30; ++i){
lg[i] = lg[i - 1] << 1;
}
}
void add(int u, int v){
edge[++tot].to = v;
edge[tot].nex = head[u];
head[u] = tot;
}
void dfs(int now, int fa){//求father数组
depth[now] = depth[fa] + 1;
father[now][0] = fa;
for(int i = 1; lg[i] <= depth[now]; ++i){
father[now][i] = father[father[now][i - 1]][i - 1];
}
for(int i = head[now]; i; i = edge[i].nex){
if(edge[i].to != fa){
dfs(edge[i].to, now);
}
}
}
int lca(int u, int v){
if(depth[u] > depth[v]){
int temp = u;
u = v;
v= temp;
}
int dif = depth[v] - depth[u];
for(int i = 0; i <= 30; ++i){//v向上跳,使u与v到达同一深度
if(lg[i] & dif){
v = father[v][i];
}
}
if(u == v){
return u;
}
for(int i = 30; i >= 0; --i){//跳到最近公共祖先的下一层
if(father[u][i] != father[v][i]){
u = father[u][i];
v = father[v][i];
}
}
return father[u][0];
}
int main(){
scanf("%d%d%d", &n, &m, &s);
int x, y;
for(int i = 0; i < n - 1; ++i){
scanf("%d%d", &x, &y);
add(x, y);
add(y, x);
}
get_lg();
dfs(s, 0);
int u, v;
while(m--){
scanf("%d%d", &u, &v);
printf("%d\n", lca(u, v));
}
return 0;
}
LCA最近公共祖先问题 倍增模板
最新推荐文章于 2025-08-13 13:28:17 发布