1. 程式人生 > 實用技巧 >倍增法求最近公共祖先

倍增法求最近公共祖先

倍增法求最近公共祖先

參考:題解 P3379 【模板】最近公共祖先(LCA)

參考:樹上倍增的寫法和應用(詳細講解,新手秒懂)

// Created by CAD
#include <bits/stdc++.h>
using namespace std;

const int maxn=5e5+5;
vector<int> g[maxn];
int f[maxn][30],dep[maxn];
int lg[maxn];
void dfs(int x,int fa){             //預處理出深度,父親節點
    f[x][0]=fa,dep[x]=dep[fa]+1;
    for(int i=1;i<=lg[dep[x]];++i)
        f[x][i]=f[f[x][i-1]][i-1];
    for(auto i:g[x])
        if(i!=fa) dfs(i,x);
}
int lca(int x,int y){                //倍增法求最近公共祖先
    if(dep[x]<dep[y]) swap(x,y);
    while(dep[x]>dep[y]) x=f[x][lg[dep[x]-dep[y]]-1];
    if(x==y) return x;
    for(int k=lg[dep[x]]-1;k>=0;--k)
        if(f[x][k]!=f[y][k])
            x=f[x][k],y=f[y][k];
    return f[x][0];
}
int main() {
    int n,q,r;  scanf("%d%d%d",&n,&q,&r);
    for(int i=1;i<=n-1;++i){
        int a,b;scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
    }
    for(int i=1;i<=n;++i)              //預處理出log_2(i)+1的值
        lg[i]=lg[i-1]+(1<<lg[i-1]==i);
    dfs(r,0);
    while(q--){
        int x,y;scanf("%d%d",&x,&y);
        printf("%d\n",lca(x,y));
    }
    return 0;
}