强连通分量&Tarjan算法——用好理解但不太正经的语言来讲

一个强连通分量,也就是一个有向图中的一个极大强连通子图。极大强连通子图?这是啥?

首先嘛,它是一个强连通图!然后就没有然后了。我本来以为“极大”似乎是什么强连通图的plus版本?结果发现一个强连通图有且只有唯一一个极大强连通子图。。。

虽然可能它本身具有它的意义于是这样叫,但在理解的基础上我们才能管这个嘛。

也就是说,

像是一个有向图中的强连通子图
或者单个点
都是一个该有向图的极大强连通子图。


如上图,每个红色的框里面的部分代表一个极大强连通子图。那大概这样的东西就是强连通分量啦!

由于每个强连通分量中的点都是联通的,所以我们在很多情况下可以将他们看作是一个整体并成同一个。缩完以后里面不就没了,环都变点了,所以原图变成了有向无环图(DAG)。

最常用的是Tarjan算法。

(叫陶尔杨,不叫太监)

当然了,Tarjan算法有向图无向图都是可以用滴。

正如标题,我们不讲得那么正式。(毕竟我菜)

Tarjan算法是以DFS的方式实现滴。想象一下,一个有向图,我们随便以一个点为起点,对它进行DFS遍历,我们对所走的路径标记一下序号,咱叫它dfs序吧。

诶,如果我们一直向下走,走着走着发现走到了一个在我们之前就走到过的点,那么这就系一个环了嘛!我们一直走,直到没法走。我们所遇到的我们走过的最早的那个点开始到我们当前最后这个点,大家都是联通的,划分为同一个强连通分量。(毕竟范围肯定是要求最大的嘛,可能这就是为啥叫“极大”吧。)

比如说这么个有向图,我们从某个点像这样搜(假如另一边几个先不管,当然肯定是要搜过去滴),最后走到第5个节点,5又发现可以回到1。于是乎,从1到5的所有结点,都在同一个强连通分量中。

具体咋实现咧。

首先是dfs序,也叫时间戳,
我们用一个数组dfn[]来存储,
哪个点的对于当前DFS的路径的dfs序是几。

其次就是怎么保存大家是一家人呢。
我们用一个数组low[],
储存当前节点能到达的最早滴已经走过的节点。

比如刚才,第5个节点的low[5]先是变成了2,后又变成了1。最后把1到5整个路径的节点都归给1。

比如我们再创建一张图,把刚才这几个点的权值都给点1,再把点1放进新图里,大家的其它边都是点1的边,点1的其它边还是点1的边,这样把所有家人融合起来成为一个点,不就缩成一个点了嘛。

每个点的low在初始都是自己嘛,
最后如果没有成为一个环中的一点,
自己就作为一个强连通分量。

无向图呢?无向图一样嘛,都是DFS,然后判定环。

最后呢,我们要注意的是,一个图在随便选一个点后进行DFS,万一有的点没有可以走到它的边呢?所以,我们要枚举每个点都去进行DFS(当然已经搜过的就没必要搜了)。即使这样,时间复杂度仍然还是线性嘛。

好啦,知道大概就是这么个玩意儿以后,你就可以去网上看大佬滴讲解啦,当然直接看代码也是可以滴。

思路其实很简单,就是打起来比较手残(指我自己)

那么我今天除了这个blog就不再写什么心得了,时间拿来打题它不香吗。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值