Tarjan——求有向图的强连通分量

本文介绍了Tarjan算法,用于寻找有向图的强连通分量。通过深度优先搜索,利用节点的index和lowlink属性来判断强连通分量,并给出算法原理及伪代码。文章还提到了强连通图、强连通分量的概念,以及在实际应用中的邻接表存储方式。
摘要由CSDN通过智能技术生成

强连通:

在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。
[vi-vj之间可以经过多个节点]

强连通图:

如果有向图G的每两个顶点都强连通,称G是一个强连通图。

强连通分量:

非强连通图有向图的极大强连通子图,称为强连通分量(strongly connected components)。
[即存在这样一个子图,图中的任意两个节点之间可以互相到达!]


在描述Tarjan算法之前,需要说明一些术语,否则可能很难弄明白算法所说的意思。

  1. 时间戳:深度优先搜索时,给每一个节点赋予一个叫做时间戳的属性。其中这个属性又分为两部分。节点v第一次被发现时给予一个开始时间戳(v.start_time),v的所有连通的节点都访问过后在给予节点v一个完成时间戳(v.finish_time)。实际上,v.start_time代表了DFS时的深度,v.finish_time表示的是DFS回溯到该节点时的所经过的点的个数。
  2. 树枝边:如果(u,v)是一条树枝边则表示u是v的父节点
  3. 后向边:如果(u,v)是一条后向边。说明v已经被访问,但其子孙后代还没有被访问完(正在访问中),且u是v的子孙后代,后向边又称返祖边.(因为回溯的时候回经过这条边找到祖先)
  4. 横叉边:如果(u,v)是一条横叉边。那么说明u、v这两个节点没有子孙关系,可能是兄弟,甚至可能不在一棵树上。

这样一些基本的概念就介绍完毕了,下面开始介绍Tarjan算法。


算法原理:

Tarjan算法的关键在于如何判定某结点是否是强连通分量的根。
注意“强连通分量的根”这一说法仅针对此算法,事实上强连通分量是没有特定的“根”的。在这里根结点指深度优先搜索时强连通分量中首个被访问的结点。

为找到根结点,我们给每个结点v一个深度优先搜索标号v.index,表示它是第几个被访问的结点(即DFS的深度)。此外,每个结点v还有一个值v.lowlink,表示从v出发经有向边可到达的所有结点中最小的index(即v和v的子树通过后向边所能到达的节点的最小DFS深度)。显然v.lowlink总是不大于v.index,且当从v出发经有向边不能到达其他结点时,这两个值相等。v.lowlink在深度优先搜索的过程中求得,v是强连通分量的根当且仅当v.lowlink = v.index。

这里我们有些疑问,按照道理来讲,v的后继节点的深度应该永远小于v的深度才对。但是不要忘记,很有可能出现“回边”(也就是后向边)的情况,这种情况下,v的后继节点的深度完全可以小于或者等于v的深度。

在算法描述用用dfn[u]存储u.index(DFS真实深度),用数组low[u]存储u.lowlink(u和u的子树通过后向边所能到达的节点的最小DFS深度
下面给出伪代码:

algorithm tarjan is
  input: 图 G = (V, E)
  output: 以所在的强连通分量划分的顶点集

  index := 0
  S := empty    // 置栈为空
  for each v in V 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值