最近公共祖先(LCA,Tarjan)
一定要耐心慢慢看
Tarjan算法的优点在于相对稳定,时间复杂度也比较居中,也很容易理解。
下面详细介绍一下Tarjan算法的基本思路:
1.任选一个点为根节点,从根节点开始。
2.遍历该点u所有子节点v,并标记这些子节点v已被访问过。
3.若是v还有子节点,返回2,否则下一步。
4.合并v到u上。
5.寻找与当前点u有询问关系的点v。
6.若是v已经被访问过了,则可以确认u和v的最近公共祖先为v被合并到的父亲节点a。
遍历的话需要用到dfs来遍历(我相信来看的人都懂吧...),至于合并,最优化的方式就是利用并查集来合并两个节点。
伪代码
Tarjan(u)//marge和find为并查集合并函数和查找函数
{for each(u,v) //访问所有u子节点v{Tarjan(v); //继续往下遍历marge(u,v); //合并v到u上标记v被访问过;}for each(u,e) //访问所有和u有询问关系的e{如果e被访问过;u,e的最近公共祖先为find(e);}
}
假设我们有一组数据 9个节点 8条边 联通情况如下:
1--2,1--3,2--4,2--5,3--6,5--7,5--8,7--9 即下图所示的树
设我们要查找最近公共祖先的点为9--8,4--6,7--5,5--3;
设f[]数组为并查集的父亲节点数组,初始化f[i]=i,vis[]数组为是否访问过的数组,初始为0;
下面开始模拟过程:
取1为根节点,往下搜索发现有两个儿子2和3;
先搜2,发现2有两个儿子4和5,先搜索4,发现4没有子节点,则寻找与其有关系的点;
发现6与4有关系,但是vis[6]=0,即6还没被搜过,所以不操作;
发现没有和4有询问关系的点了,返回此前一次搜索,更新vis[4]=1;
表示4已经被搜完,更新f[4]=2,继续搜5,发现5有两个儿子7和8;
先搜7,发现7有一个子节点9,搜索9,发现没有子节点,寻找与其有关系的点;
发现8和9有关系,但是vis[8]=0,即8没被搜到过,所以不操作;
发现没有和9有询问关系的点了,返回此前一次搜索,更新vis[9]=1;
表示9已经被搜完,更新f[9]=7,发现7没有没被搜过的子节点了,寻找与其有关系的点;
发现5和7有关系,但是vis[5]=0,所以不操作;
发现没有和7有关系的点了,返回此前一次搜索,更新vis[7]=1;
表示7已经被搜完,更新f[7]=5,继续搜8,发现8没有子节点,则寻找与其有关系的点;
发现9与8有关系,此时vis[9]=1,则他们的最近公共祖先为find(9)=5;
(find(9)的顺序为f[9]=7-->f[7]=5-->f[5]=5 return 5;)
发现没有与8有关系的点了,返回此前一次搜索,更新vis[8]=1;
表示8已经被搜完,更新f[8]=5,发现5没有没搜过的子节点了,寻找与其有关系的点;
发现7和5有关系,此时vis[7]=1,所以他们的最近公共祖先为find(7)=5;
(find(7)的顺序为f[7]=5-->f[5]=5 return 5;)
又发现5和3有关系,但是vis[3]=0,所以不操作,此时5的子节点全部搜完了;
返回此前一次搜索,更新vis[5]=1,表示5已经被搜完,更新f[5]=2;
发现2没有未被搜完的子节点,寻找与其有关系的点;
又发现没有和2有关系的点,则此前一次搜索,更新vis[2]=1;
表示2已经被搜完,更新f[2]=1,继续搜3,发现3有一个子节点6;
搜索6,发现6没有子节点,则寻找与6有关系的点,发现4和6有关系;
此时vis[4]=1,所以它们的最近公共祖先为find(4)=1;
(find(4)的顺序为f[4]=2-->f[2]=1-->f[1]=1 return 1;)
发现没有与6有关系的点了,返回此前一次搜索,更新vis[6]=1,表示6已经被搜完了;
更新f[6]=3,发现3没有没被搜过的子节点了,则寻找与3有关系的点;
发现5和3有关系,此时vis[5]=1,则它们的最近公共祖先为find(5)=1;
(find(5)的顺序为f[5]=2-->f[2]=1-->f[1]=1 return 1;)
发现没有和3有关系的点了,返回此前一次搜索,更新vis[3]=1;
更新f[3]=1,发现1没有被搜过的子节点也没有有关系的点,此时可以退出整个dfs了。
经过这次dfs我们得出了所有的答案,有没有觉得很神奇呢?是否对Tarjan算法有更深层次的理解了呢?
以上转载:https://www.cnblogs.com/JVxie/p/4854719.html (很易懂)
模板习题
最近公共祖先(LCA,Tarjan)相关推荐
- 最近公共祖先 LCA Tarjan算法
来自:http://www.cnblogs.com/ylfdrib/archive/2010/11/03/1867901.html 对于一棵有根树,就会有父亲结点,祖先结点,当然最近公共祖先就是这两个 ...
- 【C++】最近公共祖先 LCA
最近公共祖先 百科名片 简单引入 LCA的算法 暴力枚举法 Tarjan离线算法 倍增算法 例题: 题目描述 输入描述 输出描述 样例输入 样例输出 代码 百科名片 最近公共祖先 Lowest Com ...
- 图论--最近公共祖先LCA
最近公共祖先LCA LCA(Least Common Ancestors),即最近公共祖先,是指这样一个问题:在有根树中,找出某两个结点u和v最近的公共祖先(另一种说法,离树根最远的公共祖先) 最近公 ...
- 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) [No. 21]
问题: 给定一个二叉树,找到两个节点NA, NB的最近公共祖先(LCA). 比如对于下图,4 和 7 的 LCA 是6, 1和13的LCA 是 8. 我们这里先考虑一般的二叉树(BT),然后再考虑这个 ...
- 树上倍增法求最近公共祖先LCA
LCA,最近公共祖先,这个东西有很多作用,因此,如何高效求出LCA就成了一个热点的讨论话题. 下面所有的讨论都以图中这棵树为例子. 先来了解下什么是倍增吧,倍增其实就是二分的逆向,二分是逐渐缩小范围, ...
- POJ 1470 Closest Common Ancestors (最近公共祖先LCA 的离线算法Tarjan)
Tarjan算法的详细介绍,请戳: http://www.cnblogs.com/chenxiwenruo/p/3529533.html #include <iostream> #incl ...
- POJ 1330 LCA最近公共祖先 离线tarjan算法
题意要求一棵树上,两个点的最近公共祖先 即LCA 现学了一下LCA-Tarjan算法,还挺好理解的,这是个离线的算法,先把询问存贮起来,在一遍dfs过程中,找到了对应的询问点,即可输出 原理用了并查集 ...
- 与图论的邂逅05:最近公共祖先LCA
什么是LCA? 祖先链 对于一棵树T,若它的根节点是r,对于任意一个树上的节点x,从r走到x的路径是唯一的(显然),那么这条路径上的点都是并且只有这些点是x的祖先.这些点组成的链(或者说路径)就是x的 ...
- 最近公共祖先LCA 【专题@AbandonZHANG】
参考: <算法艺术与信息学竞赛> --- 刘汝佳 博客:http://blog.163.com/kevinlee_2010/blog/static/16982082020120794613 ...
最新文章
- Hive MetaStore 在快手遇到的挑战与优化
- Html5元素及基本语法
- springMVC操作mongoDB增删改查
- freecplus框架-MySQL数据库操作
- cmd下运行Oracle清屏命令
- 【转】让你的手机成为你的电脑摄像头
- CAN数据格式-ASC
- adf4351_配置MySQL以进行ADF开发
- 小班安全使用计算机教案,幼儿园小班安全教案(精选5篇)
- Linux征途服务端启动,linux征途之系统开机流程
- linux修改分辨率的命令,linux修改分辨率(命令)
- office 2003也能编辑.docx文档
- Java集成ElasticSearch及配置类工具类整理
- osgearth]样式表style中参数总结(OE官方文档翻译)
- Flutter 报错Mapping values are not allowed here. Did you miss a colon earlier?
- 从 RDO到 ADO 的移植
- 占位符前面的数字的作用
- 阿里云IoT物模型-属性,服务,事件通信的topic和payload详解——设备管理运维类
- 有点Python编程基础,怎么赚点小钱?
- P60 整型数据类型讲解
热门文章
- 小米4c原版android哪个好,小米4c和小米4哪个好
- 小米手机4c如何刷入开发版获取ROOT权限
- 被问麻了,Spring 如何处理循环依赖?
- matlab绘制sintsinwt,sin(wt)中的t单位是
- Apache SkyWalking入门学习笔记
- Ubuntu手机操作系统稳定版 20131018
- ci mysql操作_MySQL基础篇/第3篇:MySQL基本操作语句.md · icanci/MySQL-Review - Gitee.com...
- coreldraw带圈字符_coreldraw中如何使字体围绕一个圆形排列?
- 是否该读博士(ZZ)
- PEP代码规范简单总结