社区讨论

倍增求LCA 70pts求条

P3379【模板】最近公共祖先(LCA)参与者 2已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@mhjaxf6m
此快照首次捕获于
2025/11/03 23:35
4 个月前
此快照最后确认于
2025/11/03 23:35
4 个月前
查看原帖
记录:https://www.luogu.com.cn/record/234152299
CPP
#include<bits/stdc++.h>
using namespace std;
const int MaxN=5e5;

int head[MaxN+5],Next[2*MaxN+5],to[2*MaxN+5],dep[MaxN+5];
int fno[MaxN][25];
int cnt;

void add(int x,int y)
{
    Next[++cnt]=head[x];
    to[cnt]=y;
    head[x]=cnt;
}

int dfs(int n,int f)//n为当前节点编号 f为父亲编号
{
    fno[n][0]=f;//认父亲
    dep[n]=dep[f]+1;
    for(int i=1;i<=21;++i)fno[n][i]=fno[fno[n][i-1]][i-1];//倍增
    for(int i=head[n];i;i=Next[i])//递归子节点
    {
        if(to[i]!=f)//排除父亲
        {
            dfs(to[i],n);
        }
    }
    return 0;
}

int lca(int x,int y)
{
    if(x==y)return x;
    if(dep[x]<dep[y])swap(x,y);//使得x更深
    for(int trip=21;trip>=0;trip--)//调整到同一深度
    {
        if(dep[fno[x][trip]]>=dep[y])x=fno[x][trip];
    }
    if(x==y)return x;
    for(int trip=21;trip>=0;trip--)//倍增
    {
        if(fno[x][trip]==fno[y][trip])continue;
        x=fno[x][trip],y=fno[y][trip];
    }
    return fno[x][0];
}

int main()
{
    int n,m,root;
    scanf("%d %d %d",&n,&m,&root);
    --n;
    while(n--)
    {
        int a,b;
        scanf("%d %d",&a,&b);
        add(a,b); add(b,a);
    }

    dfs(root,0);
    fno[root][0]=0;
    
    while(m--)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        printf("%d\n",lca(x,y));
    }
    return 0;
}

回复

2 条回复,欢迎继续交流。

正在加载回复...