Luogu-3379 (LCA模板)

題目鏈接 https://www.luogu.org/problemnew/show/3379

#include <cstdio>
#include <algorithm>
#define Add(x,y) (to[++num]=head[x],head[x]=num,V[num]=y)
#define For(x) for(int h=head[x],o=V[h]; h; o=V[h=to[h]])
using namespace std;
int head[500005],to[1000005],V[1000005],num;
int ST[500005][25],d[500005];
int n,m,s,a,b;

void dfs(int x,int Fa,int dep){
    d[x]=dep;
    For(x) if (o!=Fa){
        ST[o][0]=x;
        dfs(o,x,dep+1);
    }
}

void getST(){
    for (int j=1; j<=20; j++)
        for (int i=1; i<=n; i++)
            ST[i][j]=ST[ST[i][j-1]][j-1];
}

int FA(int x,int y){        //x 的第 y 代祖先 
    for (int i=0; y; i++,y>>=1)
        if (y&1) x=ST[x][i];
    return x;
}

int LCA(int x,int y){
    if (d[x]<d[y]) swap(x,y);
    x=FA(x,d[x]-d[y]);      //使得 x 和 y 處於同一深度 
    if (x==y) return x;     //一樣就直接返回值 
    for (int i=20; i>=0; i--)
        if (ST[x][i]!=ST[y][i])
            x=ST[x][i],y=ST[y][i];  //一直將 x,y 往上挪找到最上面那層不一樣的
    return ST[x][0];        //再往上一層就是答案 
}

int main(){
    freopen("1.txt","r",stdin);
    scanf("%d%d%d",&n,&m,&s);
    for (int i=1; i<n; i++)
        scanf("%d%d",&a,&b),Add(a,b),Add(b,a);
    dfs(s,0,0);
    getST();
    while (m--){
        scanf("%d%d",&a,&b);
        printf("%d\n",LCA(a,b));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章