码迷,mamicode.com
首页 > 编程语言 > 详细

Tarjan算法:求解图的割点与桥(割边)

时间:2017-12-04 00:51:40      阅读:315      评论:0      收藏:0      [点我收藏+]

标签:红色   例子   深度优先   分支   pad   影响   otto   tarjan   order   

简介

割边和割点的定义仅限于无向图中。我们可以通过定义以蛮力方式求解出无向图的所有割点和割边,但这样的求解方式效率低。Tarjan提出了一种快速求解的方式,通过一次DFS就求解出图中所有的割点和割边。

欢迎探讨,如有错误敬请指正

如需转载,请注明出处 http://www.cnblogs.com/nullzx/


1. 割点与桥(割边)的定义

在无向图中才有割边和割点的定义

割点:无向连通图中,去掉一个顶点及和它相邻的所有边,图中的连通分量数增加,则该顶点称为割点。

桥(割边):无向联通图中,去掉一条边,图中的连通分量数增加,则这条边,称为桥或者割边。

割点与桥(割边)的关系

1)有割点不一定有桥,有桥一定存在割点

2)桥一定是割点依附的边。

下图中顶点C为割点,但和C相连的边都不是桥。

2. 暴力解决办法解决求解割点集和割边集

暴力法的原理就是通过定义求解割点和割边。在图中去掉某个顶点,然后进行DFS遍历,如果连通分量增加,那么该顶点就是割点。如果在图中去掉某条边,然后进行DFS遍历,如果连通分量增加,那么该边就是割边。对每个顶点或者每个边进行一次上述操作,就可以求出这个图的所有割点和割边,我们称之为这个图的割点集和割边集。

在具体的代码实现中,并不需要真正删除该顶点和删除依附于该顶点所有边。对于割点,我们只需要在DFS前,将该顶点对应是否已访问的标记置为ture,然后从其它顶点为根进行DFS即可。对于割边,我们只需要禁止从这条边进行DFS后,如果联通分量增加了,那么这条边就是割边。

3. Tarjan算法的原理

判断一个顶点是不是割点除了从定义,还可以从DFS(深度优先遍历)的角度出发。我们先通过DFS定义两个概念。

假设DFS中我们从顶点U访问到了顶点V(此时顶点V还未被访问过),那么我们称顶点U为顶点V的父顶点,V为U的孩子顶点。在顶点U之前被访问过的顶点,我们就称之为U的祖先顶点

显然如果顶点U的所有孩子顶点可以不通过父顶点U而访问到U的祖先顶点,那么说明此时去掉顶点U不影响图的连通性,U就不是割点。相反,如果顶点U至少存在一个孩子顶点,必须通过父顶点U才能访问到U的祖先顶点,那么去掉顶点U后,顶点U的祖先顶点和孩子顶点就不连通了,说明U是一个割点。

技术分享图片

 

上图中的箭头表示DFS访问的顺序(而不表示有向图),对于顶点D而言,D的孩子顶点可以通过连通区域1红色的边回到D的祖先顶点C(此时C已被访问过),所以此时D不是割点。

技术分享图片

上图中的连通区域2中的顶点,必须通过D才能访问到D的祖先顶点,所以说此时D为割点。再次强调一遍,箭头仅仅表示DFS的访问顺序,而不是表示该图是有向图。

这里我们还需要考虑一个特殊情况,就是DFS的根顶点(一般情况下是编号为0的顶点),因为根顶点没有祖先顶点。其实根顶点是不是割点也很好判断,如果从根顶点出发,一次DFS就能访问到所有的顶点,那么根顶点就不是割点。反之,如果回溯到根顶点后,还有未访问过的顶点,需要在邻接顶点上再次进行DFS,根顶点就是割点。

4. Tarjan算法的实现细节

在具体实现Tarjan算法上,我们需要在DFS(深度优先遍历)中,额外定义三个数组dfn[],low[],parent[]

1)dfn数组的下标表示顶点的编号,数组中的值表示该顶点在DFS中的遍历顺序(或者说时间戳),每访问到一个未访问过的顶点,访问顺序的值(时间戳)就增加1。子顶点的dfn值一定比父顶点的dfn值大(但不一定恰好大1,比如父顶点有两个及两个以上分支的情况)。在访问一个顶点后,它的dfn的值就确定下来了,不会再改变。

2) low数组的下标表示顶点的编号,数组中的值表示DFS中该顶点不通过父顶点能访问到的祖先顶点中最小的顺序值(或者说时间戳)。

每个顶点初始的low值和dfn值应该一样,在DFS中,我们根据情况不断更新low的值。

假设由顶点U访问到顶点V。当从顶点V回溯到顶点U时,

如果

dfn[v] < low[u]

那么

low[u] = dfn[v]

如果顶点U还有它分支,每个分支回溯时都进行上述操作,那么顶点low[u]就表示了不通过顶点U的父节点所能访问到的最早祖先节点。

 

现在我们来看一个例子,模仿程序计算各个顶点的dfn值和low值。下图中蓝色实线箭头表示已访问过的路径,无箭头虚线表示未访问路径。已访问过的顶点用黄色标记,未访问的顶点用白色标记,DFS当前正在处理的顶点用绿色表示。带箭头的蓝色虚线表示DFS回溯时的返回路径。

 

技术分享图片

当DFS走到顶点H时,有三个分支,我们假设我们先走H-I,然后走H-F,最后走H-J。从H访问I时,顶点I未被访问过,所以I的dfn和low都为9。根据DFS的遍历顺序,我们应该从顶点I继续访问。

 

 

技术分享图片

上图表示由顶点I访问顶点D,而此时发现D已被访问,当从D回溯到I时,由于

dfn[D] < dfn[I]

说明D是I的祖先顶点,所以到现在为止,顶点I不经过父顶点H能访问到的小时间戳为4。

Tarjan算法:求解图的割点与桥(割边)

标签:红色   例子   深度优先   分支   pad   影响   otto   tarjan   order   

原文地址:http://www.cnblogs.com/nullzx/p/7968110.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!