数据结构——强连通分量图算法

数据结构——强连通分量图算法

连通图

顶点的连通性

在无向图G中,若从顶点vi到顶点vj有路径(当然从vj到vi也一定有路径),则称vi和vj是连通的。

连通图

在无向图G中,若V(G)中任意两个不同的顶点vi和vj都连通(即有路径),则称G为连通图。
在有向图G中,如果两个顶点vi,vj间有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通。如果有向图G的每两个顶点都强连通,称G是一个强连通图。

连通分量

如果从任意顶点都存在一条路径达到任意一个顶点,则称这幅图是连通图。而连通分量指的是一幅图中所有极大连通子图。

无向图的连通分量

无向图的G的极大连通子图称为G的连通分量。任何连通图的连通分量都只有一个,即其本身,非连通的无向图有多个连通分量。
使用广度优先搜索或深度优先搜索来计算线性时间内图的连通分量是很直接的。无论哪种情况,从某个特定顶点v开始的搜索将在返回之前找到包含v(并且不再有)的整个连接组件。要查找图的所有连通分量,循环遍历其顶点,每当循环到达一个尚未包含在先前找到的连通分量中的顶点时,开始新的宽度第一次或深度第一次搜索。

有向图的强连通分量

有向图强连通分量:在有向图G中,如果两个顶点vi,vj间有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量。

强联通分量图算法

Kosaraju算法

算法步骤

(1) 在图G中,计算图G的反向图G’的深度优先搜索的逆后序排列。反向图是比如原图中有vi到vj的链接,那么反向图中就有vj到vi的链接。逆后序排列是指,在对一个图进行深度优先遍历时,先进行子节点的递归,再将本节点加入到一个栈中,最后依次出栈以获得的序列。逆后序排列有一个重要特性,就是如果有vj到vi的有向链接,那么实际出栈时,vj仍然排在vi的前面。
(2) 在G中进行普通的深度优先搜索,但是搜索顺序不是按照正统的顺序( i = 0, i < N )去依次搜索,而是以刚刚获得的逆后序排列的顺序进行搜索。
(3) 每个以这个逆后序排列中的元素开始的DFS搜索,找到的所有元素,都是同一个强联通分量的元素。

Tarjan算法

算法思路

Tarjan算法是基于DFS的,每个强连通分量为搜索树的一棵子树,搜索时把当前搜索树中未处理的节点加入一个栈,回溯时判断栈顶到栈中节点是否为强连通分量。为了使这颗搜索树在遇到强连通分量的节点的时候能顺利进行。在DFS时每个点都需要记录两个数组:
DFN[u]:代表u点DFS到的时间,即时间戳,简单来说就是第几个被搜索到的。可知在同一个DFS树的子树中,DFN[u]越小,则其越浅。
Low[u]:代表在DFS树中,u或u的子树能够追溯到的最早的栈中节点的时间戳。

算法步骤

(1) 数组的初始化:对图进行深度优先搜索,在搜索过程中用 DFN 记录搜索的顺序。当首次搜索到u时,DFN与 Low 数组的值都为 到该点的时间。
(2) 每搜索到一个点,将它压入栈中。如果这个点有邻居顶点就继续往下找,直到该顶点不存在未被访问的邻居顶点。
(3) 每次返回时都将子节点与该节点的Low值进行比较,谁小就取谁,保证最小的子树根。当点u 有与点u’ 相连时,如果此时u’不在栈中,u的Low值为两点的Low值中较小的一个。当点u 有与点u’ 相连时,如果此时u’在栈中,u的Low值为u的Low值和u’的DFN值中较小的一个。
(4) 每当搜索到一个点经过以上操作后(也就是子树已经全部遍历)的Low值等于DFN值(DFN[u] == Low[u]),则将它以及在它之上的元素弹出栈。这些出栈的元素组成一个强连通分量。
(5) 继续搜索,直到所有点被遍历。

算法总结

可以发现,Tarjan算法中,每个顶点都被访问了一次,且只进出了一次堆栈,每条边也只被访问了一次,所以该算法的时间复杂度为O(N+M)。Kosaraju是基于对有向图及其逆图两次DFS的方法,其时间复杂度也是O(N+M)。与Trajan算法相比,Kosaraju算法可能会稍微更直观一些。但是Tarjan只用对原图进行一次DFS,不用建立逆图,更加简洁。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值