• LCA最近公共祖先倍增法笔记


     先暂时把模板写出来,A几道题再来补充

    此模板也是洛谷上的一道模板题

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

    #pragma GCC optimize(2) //o2优化
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int L = 30;//2的指数的大小 
    const int NN = 1e6+10;
    int N,M,S;
    
    ll bit[L];
    int depth[NN];//depth[i]:节点i在树上的深度 
    int fa[NN][L]; //fa[i][j]:节点i向上走2^j次方的节点 
    vector<int> G[NN];//存图 
    
    
    void init_log(){//预先把2的多少次方计算出来 
        bit[0] = 1;
        for(int i = 1;i<L;i++)
            bit[i] = bit[i-1]*2;
    }
    
    void DFS(int u,int par){//u:当前节点 par:u的父亲节点 
        depth[u] = depth[par]+1;
        fa[u][0] = par;
        for(int i = 1;i<L;i++){
            fa[u][i] = fa[fa[u][i-1]][i-1];//计算u的各次方的祖先 
        }
        for(auto v: G[u]){//继续去遍历该节点的孩子节点 
            if(v!=par){//因为是用邻接表存的,所以需要跳过父亲节点 
                DFS(v,u);
            }
        }
    }
    
    int LCA(int a,int b){
        if(depth[a] < depth[b]) swap(a,b);//保证深度大的在前,小的在后 
        int dif = depth[a] - depth[b];//深度差 
        for(int i = L-1;i>=0;i--){
            if(bit[i] <= dif){//在不超出深度差的范围向上爬 
                a = fa[a][i];//爬到的位置 
                dif -= bit[i];//深度差更新 
            }
        }
        //此时a,b已经是相同的深度
        if(a == b) return a; //如果a,b节点已经相同,所以a,b所在的节点就是lca 
        
        for(int i = L-1;i>=0;i--){
            if(bit[i] <= depth[a] && fa[a][i] != fa[b][i]){ //bit[i]<=depth[a]:表示不跳出树之外 
                a = fa[a][i];
                b = fa[b][i];
            }
        }
        return fa[a][0]; //返回lca的儿子的父亲,也就是lca 
    }
    
    
    int main(){
    //    freopen("test.in","r",stdin);
        init_log();
        cin>>N>>M>>S;
        int u,v;
        for(int i = 1;i<=N-1;i++){ //邻接表存图 
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        DFS(S,0);
        int a,b;
        for(int i = 1;i<=M;i++){
            scanf("%d%d",&a,&b);
            int lca = LCA(a,b);
            printf("%d\n",lca);
        }
        
        
        return 0;
    }
  • 相关阅读:
    利用console控制台调试php代码
    数据库比对脚本(PHP版)
    Symfony框架系列----1.入门安装
    Symfony框架系列----常用命令
    Symfony命令行
    Linux SCP指令
    Linux 搭建SVN服务器
    Linux下 保存 git账号密码
    js 视差滚动 记录备份
    移动端 -webkit-user-select:text; ios10 bug 解决方案
  • 原文地址:https://www.cnblogs.com/bigbrox/p/11320187.html
Copyright © 2020-2023  润新知