模板 - 图论 - 最近公共祖先 - 倍增算法 - LCA

const int MAX = 100000;
vector <int> G[MAXN + 5];
int dep[MAXN + 5], fa[MAXN + 5][20 + 1];

void dfs(int u, int p) {
    dep[u] = depth[p] + 1;
    fa[u][0] = p;
    for (int i = 1; i <= 20; i++)
        fa[u][i] = fa[fa[u][i - 1]][i - 1];
    for(auto &v : G[u]) {
        if(v == p)
            continue;
        dfs(v, u);
    }
}

int LCA(int x, int y) {
    if (dep[x] < dep[y])
        swap(x, y);
    for (int i = 20; i >= 0; i--)
        if (dep[x] - (1 << i) >= dep[y])
            x = fa[x][i];
    if (x == y)
        return x;
    for (int i = 20; i >= 0; i--)
        if (fa[x][i] != fa[y][i])
            x = fa[x][i], y = fa[y][i];
    return fa[x][0];
}

原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12316367.html

时间: 2024-08-08 01:41:15

模板 - 图论 - 最近公共祖先 - 倍增算法 - LCA的相关文章

【原创】洛谷 LUOGU P3379 【模板】最近公共祖先(LCA) -&gt; 倍增

P3379 [模板]最近公共祖先(LCA) 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每行包含两个正整数x.y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树). 接下来M行每行包含两个正整数a.b,表示询问a结点和b结点的最近公共祖先. 输出格式: 输出包含M行,每行包含一个正整数,依次为每一个询问的结果. 输入输出样例 输入

最近公共祖先问题(LCA)模板

最近公共祖先问题(LCA)是求一颗树上的某两点距离他们最近的公共祖先节点,由于树的特性,树上两点之间路径是唯一的,所以对于很多处理关于树的路径问题的时候为了得知树两点的间的路径,LCA是几乎最有效的解法. 首先是LCA的倍增算法.算法主体是依靠首先对整个树的预处理DFS,用来预处理出每个点的直接父节点,同时可以处理出每个点的深度和与根节点的距离,然后利用类似RMQ的思想处理出每个点的 2 的幂次的祖先节点,这就可以用 nlogn 的时间完成整个预处理的工作.然后每一次求两个点的LCA时只要对两个

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

[模板]最近公共祖先(LCA) 题意 给一个树,然后多次询问(a,b)的LCA 模板(主要参考一些大佬的模板) #include<bits/stdc++.h> //自己的2点:树的邻接链表(静态)表示; lca 的倍增算法 //优化 log[] const int maxn=500010; int N,M,S;//S根节点标号 int head[maxn];//head[i]=k 以i为起点的第一条边是edge[k] int dep[maxn],dp[maxn][21];//dp[i][j]

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

P3379 [模板]最近公共祖先(LCA) 152通过 532提交 题目提供者HansBug 标签 难度普及+/提高 提交  讨论  题解 最新讨论 为什么还是超时.... 倍增怎么70!!题解好像有倍- 题面这个地方写错了 无论是用RMQ+dfs还是tarjan- 为什么我的倍增超时了 求助!为什么只有70分 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接

洛谷 P3379 【模板】最近公共祖先(LCA) 如题

P3379 [模板]最近公共祖先(LCA) 时空限制1s / 512MB 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每行包含两个正整数x.y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树). 接下来M行每行包含两个正整数a.b,表示询问a结点和b结点的最近公共祖先. 输出格式: 输出包含M行,每行包含一个正整数,依次为每一个询

LCA(最近公共祖先)算法

参考博客:https://blog.csdn.net/my_sunshine26/article/details/72717112 首先看一下定义,来自于百度百科 LCA(Lowest Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. 注意:这里某个节点本身也是它的祖先节点. 求最近公共祖先的算法: 1.暴力:每次查询的时间复杂度为O(N) 2.Tarjan(离线)算法:在一次遍历中把所有查询解决,预处理时间复杂度O(nlogn),每次查询

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

P3379 [模板]最近公共祖先(LCA) 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每行包含两个正整数x.y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树). 接下来M行每行包含两个正整数a.b,表示询问a结点和b结点的最近公共祖先. 输出格式: 输出包含M行,每行包含一个正整数,依次为每一个询问的结果. 输入输出样例 输入

P3379 【模板】最近公共祖先(LCA)(欧拉序+rmq)

P3379 [模板]最近公共祖先(LCA) 用欧拉序$+rmq$维护的$lca$可以做到$O(nlogn)$预处理,$O(1)$查询 从这里剻个图 #include<iostream> #include<cstdio> #include<vector> using namespace std; int read(){ char c=getchar(); int x=0; while(c<'0'||c>'9') c=getchar(); while('0'&l

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

题目链接:https://www.luogu.org/problem/P3379 题目大意: 给一棵以s为根的无向树,回答m个询问,回答出a和b最近的公共祖先. 解题报告: 倍增LCA的模板题,用一个数组 f [i] [j]表示i结点的第$2^{j}$个祖先.显然,一个点的祖先是f[i][0],对于当前点的第$2^{j}$个祖先的第$2^{j}$个祖先,等于当前点的第$2^{j+1}$个祖先,因为$2^{j}+2^{j}=2^{j+1}$.所以有递推式$f[i][j]=f[f[i][j-1]][