[知识点]最近公共祖先

1、前言

这是很重要的一个部分,其实之前很多内容均有所提及,今天把许多知识点放在一起讲,也是起一个总结的作用。

2、概念

最近公共祖先,英文简称为LCA,当且仅当存在于树之中。如假设你生了一对双胞胎,那么两门两个人的最近公共祖先就是你了。公共祖先存在很多,但是最近有且仅有一个。如图所示,ans节点就是点x和点y的LCA。

我们很多时候都需要求得LCA,如当对树上点x到点y路径进行一些操作时,首先我们要找到LCA才能得到他们的路径。求LCA的方式有很多,但是大同小异,都是向父亲节点转移。现在根据复杂度一层层来分析。

3、暴力枚举求LCA

很简单的一种方式,但是也是复杂度最高的办法。对于查询点x和点y的LCA,首先根据两点的深度,若dep[x]>dep[y],则点x向父亲节点一步步转移x=fa[x],直到dep[x]=dep[y];反之亦然。当深度相同后,则同时向上转移,即x=fa[x],y=fa[y],直到x=y,此时找到LCA,退出循环。

其基本框架就是递归,时间复杂度为O(max(dep[x],dep[y]))。

4、倍增求LCA

(暂缺)

5、Tarjan求LCA

(暂缺)

6、树链剖分求LCA

之前在单独讲解树链剖分的时候,就已经体现出了它的这一特性。我们为什么要划出重链?划出重链之后为什么要用线段树来维护每一条边?其作用就在于重边总是相连,当得知每条重链的顶端之后,我们向上跑LCA就是简单的一步步爬了,在最优情况下,可以做到O(1)。然而具体实现的话,大家可以参照“树链剖分”专题(),

时间: 2024-11-05 13:34:12

[知识点]最近公共祖先的相关文章

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

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

50、树中两个节点的公共祖先

详细的询问: 1.该树是二叉查找树? 最近公共祖先----二叉查找树:(http://www.lintcode.com/problem/lowest-common-ancestor/) 思路:利用左子树特点:左子树 < 根 <= 右,输入节点跟根节点比较,都小于,在左子树,都大约右子树,递归的去遍历:找到当前节点在两个输入大小之间,当前节点就是. 递归和非递归 public class Solution { public TreeNode lowestCommonAncestor(TreeNo

[最近公共祖先] POJ 3728 The merchant

The merchant Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 4556   Accepted: 1576 Description There are N cities in a country, and there is one and only one simple path between each pair of cities. A merchant has chosen some paths and w

lca最近公共祖先(st表)

大体思路 1.求出每个元素在树中的深度 2.用st表预处理的方法处理出f[i][j],f[i][j]表示元素i上方第2^j行对应的祖先是谁 3.将较深的点向上挪,直到两结点的深度相同 4.深度相同后,祖先可能就在上方,再走几步就到了,于是两个点同时向上移 具体的方法和代码贴在下面 ↓ 具体来看 1.求出每个元素在树中的深度 //求每个节点在树中的深度 void dfs(int pos,int pre)//pre是pos的父节点 { for(int i=0;i<v[pos].size;i++)//

LCA(最近公共祖先)--tarjan离线算法 hdu 2586

HDU 2586 How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11320    Accepted Submission(s): 4119 Problem Description There are n houses in the village and some bidirectional roads c

最近公共祖先 LCA Tarjan算法

来自:http://www.cnblogs.com/ylfdrib/archive/2010/11/03/1867901.html 对于一棵有根树,就会有父亲结点,祖先结点,当然最近公共祖先就是这两个点所有的祖先结点中深度最大的一个结点. 0 | 1 /   \ 2      3 比如说在这里,如果0为根的话,那么1是2和3的父亲结点,0是1的父亲结点,0和1都是2和3的公共祖先结点,但是1才是最近的公共祖先结点,或者说1是2和3的所有祖先结点中距离根结点最远的祖先结点. 在求解最近公共祖先为问

最近公共祖先

0. 概要 最近公共祖先,指的是在一颗有根树上,两个点的公共祖先中,深度最大的那个. 最直接的应用是求无权树上两个点的最短距离:$distance(u, v)  = depth(u) + depth(v) - 2depth(lca(u, v))$. 再有其他的应用则以后再提. 1 基于 dfs 序列上 RMQ 的稀疏表解法 首先 dfs 遍历树,如下如图中蓝色箭头的顺序.并记录: 1. 遍历点序列 $euler[] = \{1, 2, 1, 3, 5, 3, 6 ……$ 2. 每个点首次在 eu

LeetCode OJ:Lowest Common Ancestor of a Binary Tree(最近公共祖先)

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w

最近公共祖先(三种算法)

最近研究了一下最近公共祖先算法,根据效率和实现方式不同可以分为基本算法.在线算法和离线算法.下面将结合hihocoder上的题目分别讲解这三种算法. 1.基本算法 对于最近公共祖先问题,最容易想到的算法就是从根开始遍历到两个查询的节点,然后记录下这两条路径,两条路径中距离根节点最远的节点就是所要求的公共祖先. 题目参见 #1062 : 最近公共祖先·一 附上AC代码,由于记录的方式采取的是儿子对应父亲,所以实现的时候有点小技巧,就是对第一个节点的路径进行标记,查找第二个节点的路径时一旦发现访问到