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));
    }
}

猜你喜欢

转载自blog.csdn.net/jackypigpig/article/details/78453414