zoukankan      html  css  js  c++  java
  • Luogu P3379 【模板】最近公共祖先(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
    ",t);
        }
        return 0;
    }
  • 相关阅读:
    使用ssh公钥实现ssh免密码登录
    如何定义领域模型(概念模型)
    17.python字符编码检测——chardet
    21.python对象的浅拷贝和深拷贝
    15.序列化python对象
    18.python的打包和发布
    16.python的网络编程
    13.python的文件操作
    linux下python、django框架的配置
    14.python的xml操作
  • 原文地址:https://www.cnblogs.com/mogeko/p/10301615.html
Copyright © 2011-2022 走看看