Luogu P3379 【模板】最近公共祖先(LCA)

本文深入探讨了LCA(最近公共祖先)算法在图论中的应用,详细讲解了如何预处理节点跳跃以高效求解LCA问题。通过具体代码示例,展示了如何在双向图中实现LCA算法,包括节点深度计算、跳跃表初始化及LCA查找过程。

qwq

预处理出从$x$节点向上跳2i个节点的序号$p[x][i]$及节点深度$dpth[x]$,

寻找$lca$时,从$Max$(可能的最大深度)到0枚举$i$,

首先把较深的一个节点向上跳至深度相同,

然后两个点同步动作,若$p[x][i]≠p[y][i]$则跳。

最终返回他们的父亲$p[x][0]$即为$lca$。

注意双向边要开2倍

#include<cstdio>
#include<iostream>
#include<cmath>
#define MogeKo qwq

using namespace std;
const int maxn = 500005*2;
int head[maxn],to[maxn],nxt[maxn],dpth[maxn];
int n,m,s,u,v,cnt,p[maxn][30];


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

void dfs(int x,int fa) {
    dpth[x] = dpth[fa]+1;
    p[x][0] = fa;
    for(int i = 1; (1 << i)<=dpth[x]; i++)
        p[x][i] = p[p[x][i-1]][i-1];
    for(int i = head[x]; i; i = nxt[i]) {
        if(to[i] == fa)continue;
        dfs(to[i],x);
    }
}

int lca(int a,int b) {
    if(dpth[a] < dpth[b])
        swap(a,b);
    for(int i = log2(dpth[a]); i >= 0; i--)
        if(dpth[a]-(1<<i) >= dpth[b])
            a = p[a][i];
    if(a == b)return a;
    for(int i = log2(dpth[a]);i >= 0;i--)
        if(p[a][i] != p[b][i]){
            a = p[a][i];
            b = p[b][i];
        }
    return p[a][0];
}


int main() {
    scanf("%d%d%d",&n,&m,&s);
    for(int i = 1;i <= n-1;i++){
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    dfs(s,-1);
    for(int i = 1;i <= m;i++){
        scanf("%d%d",&u,&v);
        int t = lca(u,v);
        printf("%d\n",t);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/mogeko/p/10301615.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值