洛谷博客
树上倍增
P3379 【模板】最近公共祖先(LCA)
#include <math.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#define MAXN 500005
int prn,cnt,n,m,s;
int head[MAXN],fa[MAXN][20],dep[MAXN];
struct node{
int to,next;
}map[2*MAXN];
void add(int u,int v){
map[++cnt] = (node){v,head[u]};
head[u] = cnt;
}
void dfs(int u){
for(int i=1;i<=(int)log2(n);i++){
if(!fa[u][i-1]) break;
fa[u][i] = fa[fa[u][i-1]][i-1];
}
for(int k=head[u];k;k=map[k].next){
int v = map[k].to;
if(v != fa[u][0]){
dep[v] = dep[u]+1;
fa[v][0] = u;
dfs(v);
}
}
}
int LCA(int x, int y){
if(dep[x] < dep[y]) swap(x,y);
int delta = dep[x]-dep[y];
for(int i=0;i<=(int)log2(n);i++)
if((1<<i) & delta)
x = fa[x][i];
if(x == y) return x;
for(int i=(int)log2(n);i>=0;i--){
int t1 = fa[x][i];
int t2 = fa[y][i];
if(t1 != t2){
x = t1;
y = t2;
}
}
return fa[x][0];
}
int main(void){
cin >> n >> m >> s;
for(int i=1;i<=n-1;i++){
int u,v;
cin >> u >> v;
add(u,v);
add(v,u);
}
dfs(s);
for(int i=1;i<=m;i++){
int u,v;
cin >> u >> v;
cout << LCA(u,v) << endl;
}
return 0;
}