首页 > 其他分享 >【模板】最近公共祖先(LCA)

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

时间:2023-07-24 20:11:05浏览次数:37  
标签:nxt return fa 祖先 int LCA root 模板

posted on 2021-08-04 14:22:40 | under 学术 | source

LCA,Least Common Ancestors,最近公共祖先。

倍增。

首先预处理出数组 \(d_i\) 和 \(f_{i,j}\)。

  • \(d_i\) 表示第 \(i\) 个节点的深度。
    转移方程:\(d_{i}=d_{\text{fa}}+1\)
  • \(f_{i,j}\) 表示第 \(i\) 个节点的第 \(2^j\) 级祖先。
    转移方程:\(f_{i,0}=\text{fa},f_{i,j}=f_{f_{i,j-1},j-1}\)

接着是 LCA。分成以下几个步骤:

  1. 把 \(x,y\) 跳到同一层。
  2. 使用倍增思想把 \(x,y\) 跳到离 LCA 最近的节点。
  3. 最终 \(f_{x,0}\) 或 \(f_{y,0}\) 为 \(x,y\) 的 LCA。
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
template<int N,int M> struct Graph{
    int cnt,head[N+10];
    struct Edge{
        int s,e,w,nxt;
        Edge(int s=0,int e=0,int w=0,int nxt=0):
            s(s),e(e),w(w),nxt(nxt){}
    } a[(M<<1)+10];
    Graph():cnt(0){memset(head,0,sizeof head);}
    void add(int s,int e,int w=0){a[++cnt]=Edge(s,e,w,head[s]),head[s]=cnt;}
    void link(int s,int e,int w=0){add(s,e,w),add(e,s,w);}
};
template<int N> struct Math{
    int lg[N+10];
    Math(){
        lg[0]=-1;
        for(int i=1;i<=N;i++) lg[i]=lg[i>>1]+1;
    }
    int log(int x){return lg[x];}
    int pow(int x){return 1<<x;}
};
int n,m;
Graph<500010,500010> g;
Math<5000010> math;
int f[500010][21],d[500010];
void dfs(int root,int fa){
    f[root][0]=fa,d[root]=d[fa]+1;
    for(int i=1;i<=math.log(d[root]);i++){
        f[root][i]=f[f[root][i-1]][i-1];
    }
    for(int i=g.head[root];i;i=g.a[i].nxt){
        int to=g.a[i].e;
        if(to!=fa) dfs(to,root);
    }
}
int lca(int x,int y){
    if(d[x]<d[y]) swap(x,y);
    int jmp=d[x]-d[y];
    for(int i=math.log(jmp);i>=0;i--){
        if((jmp>>i)&1) x=f[x][i];
    }
    if(x==y) return x;
    for(int i=math.log(n);i>=0;i--){
        if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    }
    return f[x][0];
}
int root;
int main(){
    cin>>n>>m>>root;
    for(int i=1;i<=n-1;i++){int x,y;
        cin>>x>>y;
        g.link(x,y);
    }
    dfs(root,root);
    for(int i=1;i<=m;i++){int x,y;
        cin>>x>>y;
        cout<<lca(x,y)<<endl;
    }
    return 0;
}

标签:nxt,return,fa,祖先,int,LCA,root,模板
From: https://www.cnblogs.com/caijianhong/p/template-lca.html

相关文章

  • GlobalCache 工具类
    packagecom.neo.config;importorg.springframework.stereotype.Component;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;importjava.util.concurrent.Executors;importjava.util.concurrent.ScheduledExecutorService;importjava.util.concurren......
  • 200种转场技巧——高效套用模板
    用别人已经帮我们做好的转场用别人做好的序列要注意把这个点掉那么拖进来的东西都是散装的,而不是一个序列这个mp4是他帮我们预染过的,我们在用的时候要把这个mp4删掉......
  • .net core razor发送邮件模板
    .NETCoreRazor发送邮件模板实现步骤概述在本文中,我将指导你如何在.NETCoreRazor项目中实现发送邮件模板。我们将使用.NETCore的SmtpClient类和Razor模板引擎来创建和发送包含动态内容的电子邮件。步骤步骤描述1引入必要的命名空间2创建Razor视图和模型3......
  • 类模板
    类模板定义所谓类模板,实际是建立一个通用类,其数据成员,成员函数的返回类型和形参类型不具体指定,用一个虚拟的类型来代表。使用类模板定义对象时,系统会根据实参的类型来取代类模板中虚拟类型从而实现了不同类的功能定义一个类模板与定义函数模板的格式类似,必须以关键字template开......
  • java 文档注释模板
    Java文档注释模板什么是文档注释?在Java中,文档注释是一种特殊的注释形式,用于为代码提供详细的说明和描述。它们不仅可以帮助开发人员更好地理解代码的用途和功能,还可以作为自动生成API文档的基础。文档注释的格式以/**开始,以*/结束,中间的内容可以使用HTML标签来格式化......
  • position为absolute的元素的生成盒的包含块是其position为absolute、relative、fixed
     蓝色区域为.parent的contentbox。由此可以看出,规范中所说的,若某元素的position为absolute,其视口应该为其第一个position为absolute、relative或fixed的祖先元素的内容边界,而不是内边距边界。......
  • 二分查找模板
    目录一、整数二分1.1整数二分查找模板1.1.1寻找右边界的二分查找1.1.2寻找左边界的二分查找二、浮点数二分2.1浮点数二分查找模板三、使用STL进行二分查找3.1std::binary_search3.2std::lower_bound3.3std::upper_bound3.4std::equal_range一、整数二分二分查找分为整数......
  • 【模板】线段树优化建图
    区间连区间luoguP6348[PA2011]Journeys略带卡常#include<bits/stdc++.h>usingnamespacestd;vector<pair<int,int>>e[4200001];intdis[4200001],id[4200001];intlson(intl){returnl*2;}intrson(intl){returnl*2+1;}voidbuild(int......
  • 【模板】图的计数相关:行列式及求值、Matrix-Tree 定理、BEST 定理、LGV 引理
    归类为线性代数、图论。证明都是神仙,特别是名字带“理”的,不证了。行列式定义行列式(Determinant)是对\(n\)阶方阵\(A\)定义的,是一个标量。\(A\)的\(n\)阶行列式\(det(A)\)或\(|A|\)定义如下:\[det(A)=\sum_p(-1)^{\mu(p)}\prod_{i}A[i][p_i].\]这里将排列的逆序对数......
  • 三维凸包 模板
    只会写增量法orz例题:P2287随机种子0x383494被卡了精度,eps=1e-10太大了#include<cstdio>#include<iostream>#include<bitset>#include<list>#include<random>#include<cmath>#include<algorithm>#defineUP(i,s,e)for(autoi=s;......