[知识点]最近公共祖先LCA
UPDATE(20180822):重写部分代码。
1、前言
最近公共祖先(LCA),作为树上问题,应用非常广泛,而求解的方式也非常多,复杂度各有不同,这里对几种常用的方法汇一下总。
2、基本概念和暴力算法
最近公共祖先,顾名思义,指的是两个点的公有祖先中,最近的那个点。它显然不会作为一个单独的知识点拿出来考,但是在很多题目中,出现的频率很高,不同场合用不同的方法。先考虑最简单的做法。找祖先,显然是从所查询的两个点从下往上爬,直到两个点出现第一次重叠时,就是最近公共祖先了。首先我们预处理出所有点的深度及父亲节点。由于两个点深度可能不同,首先我们要保证深度大的点先往上爬到与另一个点深度相同的地方,然后两个点同时向上爬,直到出现重叠。代码如下:
int lca_n() {
if (d[x] < d[y]) swap(x, y);
while (d[x] != d[y]) x = fa[x];
while (x != y) x = fa[x], y = fa[y];
return x;
}
3、倍增LCA
倍增这个概念听名字很好理解,知道倍增思想的,直接运用到求LCA并不是不好理解。首先我们需要预处理出所有节点的各种祖宗关系,p[i][j]记录节点i的第2^j个祖先,j = 0时,就是他的父亲节点。同上述暴力算法,我们从询问的两个点开始,往他们的这些倍数祖先向上爬,若第2^i个祖先不同,则从第2^(i - 1)个祖先开始,从头开始倍增。时间复杂度为 log 级别。代码如下:
void prep() {
for (int i = ; i <= n; i++) p[i][] = fa[i];
for (int j = ; ( << j) <= n; j++)
for (int i = ; i <= n; i++)
if (p[i][j - ]) p[i][j] = p[p[i][j - ]][j - ];
} int lca_h() {
if (d[x] < d[y]) swap(x, y);
while (d[x] != d[y]) {
int o = ;
while (d[p[x][o]] > d[y]) o++;
x = p[x][o - ];
}
while (x != y) {
int o = ;
while (p[x][o] != p[y][o]) o++;
x = p[x][o - ], y = p[y][o - ];
}
return x;
}
4、树链剖分LCA
树链剖分详细概念见(http://www.cnblogs.com/jinkun113/p/4683299.html)。为什么树链剖分可以跑LCA?原文提得很清楚,在把重链划分出来之后,可以确定的是重链要么单独一条存在,要么必定相连,故可以用线段树来维护。
树链剖分的优势和倍增是一样的,都可以跳过一些不必要的部分,若当前点的重链顶端不是父亲节点,可以利用线段树直接从当前点跳到顶端。这样可以达到减小复杂度的目的。
这里写出树链剖分DFS预处理和LCA核心代码的最新版本。代码到树链剖分那篇文章中找吧。
5、Tarjan LCA
(暂略)
[知识点]最近公共祖先LCA的更多相关文章
- Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集)
Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集) Description sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为 ...
- POJ 1470 Closest Common Ancestors(最近公共祖先 LCA)
POJ 1470 Closest Common Ancestors(最近公共祖先 LCA) Description Write a program that takes as input a root ...
- POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)
POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...
- [模板] 最近公共祖先/lca
简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...
- 【lhyaaa】最近公共祖先LCA——倍增!!!
高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...
- POJ 1470 Closest Common Ancestors (最近公共祖先LCA 的离线算法Tarjan)
Tarjan算法的详细介绍,请戳: http://www.cnblogs.com/chenxiwenruo/p/3529533.html #include <iostream> #incl ...
- 【Leetcode】查找二叉树中任意结点的最近公共祖先(LCA问题)
寻找最近公共祖先,示例如下: 1 / \ 2 3 / \ / \ 4 5 6 7 / \ ...
- 最近公共祖先LCA(Tarjan算法)的思考和算法实现
LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了f ...
- 查找最近公共祖先(LCA)
一.问题 求有根树的任意两个节点的最近公共祖先(一般来说都是指二叉树).最近公共祖先简称LCA(Lowest Common Ancestor).例如,如下图一棵普通的二叉树. 结点3和结点4的最近公共 ...
随机推荐
- 使用mybatis动态where字句方法
上篇文章介绍了如何使用mybatis-generator生成实体类.Mapper接口代码,其中生成的Mapper接口代码是不带ByExample方法的.本篇文章将介绍如何使用mybatis-gener ...
- AutoDesk公司搞的fbx模型格式
FBX® data exchange technology is a 3D asset exchange format that facilitates higher-fidelity data ex ...
- switch的对象不能为null
我写的NPE 虽然不多, 但几乎每次系统出问题的时候,看到api返回值是空的,绝大多数是NPE造成的. 这时候会感慨一下谁写的bug,然后去补判空代码. 最近抽风,开始给自己写的代码添加UnitTes ...
- 基于OceanStor Dorado V3存储之数据保护 Hyper 特性
基于OceanStor Dorado V3存储之数据保护 Hyper 特性 1.1 快照 1.2 HyperCDP 1.3 HyperCopy 1.4 克隆(HyperClone) 1.5 ...
- 阿里云(百度云)Linux系统挂载磁盘
阿里云(百度云)Linux系统挂载磁盘
- 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP)
高性能TcpServer(C#) - 1.网络通信协议 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP) 高性能TcpS ...
- 如何通过调优攻破 MySQL 数据库性能瓶颈?
一.前言 MySQL调优对于很多程序员而言,都是一个非常棘手的问题,多数情况都是因为对数据库出现问题的情况和处理思路不清晰.在进行MySQL的优化之前必须要了解的就是MySQL的查询过程,很多的查询优 ...
- python 父类方法中使用不同的子类中的不同类对象
# coding:utf-8 class Animal(object): def __init__(self): self._name = None self._f = None def eat(se ...
- FastReport的模板文件frx文件啊怎样打开并编辑修改
场景 FastReport安装包下载.安装.去除使用限制以及工具箱中添加控件: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...
- Mac破解百度云
https://github.com/CodeTips/BaiduNetdiskPlugin-macOS