tarjan算法大意
Tarjan算法 (以发现者Robert Tarjan命名)是一个在图中寻找强连通分量的算法。算法的基本思想为:任选一结点开始进行深度优先搜索dfs(若深度优先搜索结束后仍有未访问的结点,则再从中任选一点再次进行)。搜索过程中已访问的结点不再访问。搜索树的若干子树构成了图的强连通分量。
应用到咱们要解决的LCA问题上,则是:对于新搜索到的一个结点u,先创建由u构成的集合,再对u的每颗子树进行搜索,每搜索完一棵子树,这时候子树中所有的结点的最近公共祖先就是u了。
引用此文的一个例子,如下图(不同颜色的结点相当于不同的集合):
假设遍历完10的孩子,要处理关于10的请求了,取根节点到当前正在遍历的节点的路径为关键路径,即1-3-8-10,集合的祖先便是关键路径上距离集合最近的点。
比如:
- 1,2,5,6为一个集合,祖先为1,集合中点和10的LCA为1
- 3,7为一个集合,祖先为3,集合中点和10的LCA为3
- 8,9,11为一个集合,祖先为8,集合中点和10的LCA为8
- 10,12为一个集合,祖先为10,集合中点和10的LCA为10
得出的结论便是:LCA(u,v)便是根至u的路径上到节点v最近的点。
2.2、Tarjan算法如何而来
但关键是 Tarjan算法是怎么想出来的呢?再给定下图,你是否能看出来:分别从结点1的左右子树当中,任取一个结点,设为u、v,这两个任意结点u、v的最近公共祖先都为1。
于此,我们可以得知:若两个结点u、v分别分布于某节点t 的左右子树,那么此节点 t即为u和v的最近公共祖先。更进一步,考虑到一个节点自己就是LCA的情况,得知:
- 若某结点t 是两结点u、v的祖先之一,且这两结点并不分布于该结点t 的一棵子树中,而是分别在结点t 的左子树、右子树中,那么该结点t 即为两结点u、v的最近公共祖先。
这个定理就是Tarjan算法的基础。
一如上文1.1节我们得到的结论:“如果当前结点t 满足 u <t < v,说明u和v分居在t 的两侧,故当前结点t 即为最近公共祖先”。
而对于本节开头我们所说的“如果要求多个任意两个结点的最近公共祖先,则相当于是批量查询”,即在很多组的询问的情况下,或许可以先确定一个LCA。例如是根节点1,然后再去检查所有询问,看是否满足刚才的定理,不满足就忽视,满足就赋值,全部弄完,再去假设2号节点是LCA,再去访问一遍。
可此方法需要判断一个结点是在左子树、还是右子树,或是都不在,都只能遍历一棵树,而多次遍历的代价实在是太大了,所以我们需要找到更好的方法。这就引出了下面要阐述的Tarjan算法,即每个结点只遍历一次,怎么做到的呢,请看下文讲解。
2.3、Tarjan算法流程
Tarjan算法流程为:
Procedure dfs(u);
begin
设置u号节点的祖先为u
若u的左子树不为空,dfs(u - 左子树);
若u的右子树不为空,dfs(u - 右子树);
访问每一条与u相关的询问u、v
-若v已经被访问过,则输出v当前的祖先t(t即u,v的LCA)
标记u为已经访问,将所有u的孩子包括u本身的祖先改为u的父亲
end
普通的dfs 不能直接解决LCA问题,故Tarjan算法的原理是dfs + 并查集,它每次把两个结点对的最近公共祖先的查询保存起来,然后dfs 更新一次。如此,利用并查集优越的时空复杂度,此算法的时间复杂度可以缩小至O(n+Q),其中,n为数据规模,Q为询问个数。
2.4、Tarjan算法的应用举例
引用此文中的一个例子。
i) 访问1的左子树
|
STEP 1:从根结点1开始,开始访问结点1、2、3 |
||||||||
|
节点 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
祖先 |
1 |
2 |
3 |
|||||
|
STEP 2:2的左子树结点3访问完毕 |
||||||||
|
节点 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
祖先 |
1 |
2 |
2 |
|||||
|
STEP 3:开始访问2的右子树中的结点4、5、6 |
||||||||
|
节点 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
祖先 |
1 |
2 |
2 |
4 |
5 |
|||
|
STEP 4:4的左子树中的结点5访问完毕 |
||||||||
|
节点 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
祖先 |
1 |
2 |
2 |
4 |
4 |
|||
|
STEP 5:开始访问4的右子树的结点6 |
||||||||
|
节点 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
祖先 |
1 |
2 |
2 |
4 |
4 |
6 |
||
|
STEP 6:结点4的左、右子树均访问完毕,故4、5、6中任意两个结点的LCA均为4 |
||||||||
|
节点 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
祖先 |
1 |
2 |
2 |
4 |
4 |
4 |
||
|
STEP 7:2的左子树、右子树均访问完毕,故2、3、4、5、6任意两个结点的LCA均为2 |
||||||||
|
节点 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
祖先 |
1 |
2 |
2 |
2 |
2 |
2 |
||
如上所述:进行到此step7,当访问完结点2的左子树(3),和右子树(4、5、6)后,结点2、3、4、5、6这5个结点中,任意两个结点的最近公共祖先均为2。
ii) 访问1的右子树
|
STEP 8:1的左子树访问完毕,开始访问1的右子树 |
||||||||
|
节点 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
祖先 |
1 |
1 |
1 |
1 |
1 |
1 |
||
|
STEP 9:开始访问1的右子树中的结点7、8 |
||||||||
|
节点 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
祖先 |
1 |
1 |
1 |
1 |
1 |
1 |
7 |
|
|
STEP 10 |
||||||||
|
节点 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
祖先 |
1 |
1 |
1 |
1 |
1 |
1 |
7 |
8 |
|
STEP 11 |
||||||||
|
节点 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
祖先 |
1 |
1 |
1 |
1 |
1 |
1 |
7 |
7 |
|
STEP 12:1的右子树中的结点7、8访问完毕 |
||||||||
|
节点 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
祖先 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
当进行到此step12,访问完1的左子树(2、3、4、5、6),和右子树(7、8)后,结点2、3、4、5、6、7、8这7个结点中任意两个结点的最近公共祖先均为1。
|
STEP 13:1的左子树、右子树均访问完毕 |
||||||||
|
节点 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
祖先 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
tarjan算法大意的更多相关文章
- tarjan算法 POJ3177-Redundant Paths
参考资料传送门 http://blog.csdn.net/lyy289065406/article/details/6762370 http://blog.csdn.net/lyy289065406/ ...
- HDU4612(Warm up)2013多校2-图的边双连通问题(Tarjan算法+树形DP)
/** 题目大意: 给你一个无向连通图,问加上一条边后得到的图的最少的割边数; 算法思想: 图的边双连通Tarjan算法+树形DP; 即通过Tarjan算法对边双连通缩图,构成一棵树,然后用树形DP求 ...
- tarjan算法(求强连通子块,缩点)
tarjan算法求图中的强连通子图的个数. #include<iostream> #include<stack> #include<queue> #include& ...
- BZOJ 1123 [POI2008]BLO(Tarjan算法)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1123 [题目大意] Byteotia城市有n个towns,m条双向roads. 每条r ...
- tarjan算法,一个关于 图的联通性的神奇算法
一.算法简介 Tarjan 算法一种由Robert Tarjan提出的求解有向图强连通分量的算法,它能做到线性时间的复杂度. 我们定义: 如果两个顶点可以相互通达,则称两个顶点强连通(strongly ...
- POJ 2762 Going from u to v or from v to u? Tarjan算法 学习例题
Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 17104 Accepted: 4594 Description In o ...
- 【强联通图 | 强联通分量】HDU 1269 迷宫城堡 【Kosaraju或Tarjan算法】
为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明 ...
- hdu 2586 How far away?(LCA模板题+离线tarjan算法)
How far away ? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- 割点 —— Tarjan 算法
由于对于这一块掌握的十分不好,所以在昨天做题的过程中一直困扰着我,好不容易搞懂了,写个小总结吧 qwq~ 割点 概念 在无向连通图中,如果将其中一个点以及所有连接该点的边去掉,图就不再连通,那么这个点 ...
随机推荐
- 微软TTS示例
#include "sphelper.h" #include "sapi.h" #pragma comment(lib, "sapi.lib" ...
- hadoop笔记之MapReduce的应用案例(利用MapReduce进行排序)
MapReduce的应用案例(利用MapReduce进行排序) MapReduce的应用案例(利用MapReduce进行排序) 思路: Reduce之后直接进行结果合并 具体样例: 程序名:Sort. ...
- Javascript 学习笔记 无缝滚动
效果 : 鼠标移入图片 停止滚动, 鼠标移出自动滚动 可以调整向左或右方向滚动 <style type="text/css"> * { margin:; padding ...
- JBoss部属和EJB调用-EJB3.0入门经典学习笔记(2)
目录 1. 在JBoss中部属 2. 在Tomcat中调用EJB 3. 在JBoss中调用EJB 1. 在JBoss中部属 1) JBoss的配置目录 路径D:\Java\jboss6\serv ...
- MapReduce ---- TD-IDF
1.TF-IDF TF-IDF(term frequency/inverse document frequency) 的概念被公认为信息检索中最重要的发明.描述单个term与特定document的相关 ...
- 基本数据结构简介--ath9k网卡驱动开发总结(二)
ath9k驱动代码主要数据结构概览. (1)在ath9k的驱动中,几乎是最顶层的数据结构是ath_softc,这个数据结构几乎随处可见.ath_softc是硬件与MAC层进行交互的中间载体,很多有用的 ...
- 一次性关闭所有的Activity
原文:一次性关闭所有的Activity 一次性关闭所有的Activity ActivityManager am = (ActivityManager)getSystemService (Context ...
- 清风注解-Swift程序设计语言
前言 Apple 发布了全新的 Swift 程序设计语言,用来开发 iOS 和 OS X 平台的应用程序.其目的不言而喻:就是为了给老迈的 Objective-C 一个合适接班人!因此,不难预见,未来 ...
- 【Cocos2d TestCpp实例模仿一】-- ActionsTest
转载请注明出处:http://blog.csdn.net/oyangyufu/article/details/25252539 CCActionInterval(持续性动作) 位置性变化动作以To结束 ...
- XX秘籍
第一课 一个男人在他妻子洗完澡后准备进浴室洗澡.这时,门铃响了. 妻子迅速用浴巾裹住自己冲到门口. 当她打开门时,邻居鲍勃站在那儿. 在她开口前,鲍勃说,“你如果把浴巾拿掉,我给你800美元.” 想了 ...
