倍增求lca

发布时间 2023-09-09 17:02:45作者: dgdger

步骤:

1.前置准备:lg数组,depth数组,fa数组

2.若x与y不在同一深度,先让它们跳到同一深度

3.开始倍增往上跳

代码:

#include<iostream>
#include<cstdio>
using namespace std;
const long long N=1e6+10;
int n,m,s,h1,h2,lg[N],fa[500010][30],depth[N];
int tot=0,head[N],nxt[N],v[N];
void add(int x,int y){
    tot++;
    v[tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}
void dfs(int now,int fath){
    fa[now][0]=fath;
    depth[now]=depth[fath]+1;
    for(int i=1;i<=lg[depth[now]];i++){
        fa[now][i]=fa[fa[now][i-1]][i-1];
    }
    for(int i=head[now];i;i=nxt[i]){
        if(v[i]!=fath) dfs(v[i],now);
    }
}
int lca(int x,int y){
    if(depth[x]<depth[y]) swap(x,y);
    while(depth[x]>depth[y]){
        x=fa[x][lg[depth[x]-depth[y]]-1];
    }
    if(x==y) return x;
    for(int i=lg[depth[x]]-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,&s);
    for(int i=1;i<=n;i++){
        lg[i]=lg[i-1]+(1<<lg[i-1]==i);
    }
    for(int i=1;i<n;i++){
        scanf("%d%d",&h1,&h2);
        add(h1,h2);
        add(h2,h1);
    }
    dfs(s,0);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&h1,&h2);
        printf("%d\n",lca(h1,h2));
    }
    return 0;
}