记强连通分量的学习

本文介绍了有向图的强连通分量概念,并详细解析了Tarjan算法用于求解强连通分量的过程,通过实例分析了算法的工作原理,最后提供了一道洛谷OJ题目作为应用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一部分------求强连通分量

1.强连通分量的概念

"有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量(strongly connected components)。"                             -------------来源:百度百科

我的理解就是在有向图中找到一个最大的子图,使得这个子图的任意两点都能够相互到达,那么这个子图就被称作强连通分量,如果只有一个点那么也称之为强连通分量,但是如果这个子图增加一个点后任然符合"任意两点都能够相互到达"那就不能称之为强连通分量,而是强连通图

图中ABC可相互到达,所以(A,B,C)为一个强连通分量,D为一个强连通分量,共两个强连通分量

图中1234四个点可相互到达,所以(1,2,3,4)可相互到达,5和6各为一个强连通分量,共三个强连通分量

2.如何求强连通分量

这里我介绍的方法是Tarjan算法

依旧先举一个图例


我们现在从1开始对它进行一个dfs遍历,按照遍历的深度,1为第一层,2和3为第二层,4和5为第三层,6为第四层(可以自己在纸上画一画),我们发现4->1这条红线代表的有向边十分特别,因为其他的有向边都朝着更深的层次的结点,而这条特殊的边却指向了比自己深度更小的结点.

现在我们假设存在这么一条边,从一个点i出发,一直向下遍历,然后到达了一个点j时,我们发现这个j点竟然有一条指向i的边!那么显然从点j出发可以回到点i从而再次回到点j,显然从ij这条路径上的所有点与ij共同构成了一个环,而这个环上的所有点必然是强连通的, 但是我们要求的是强连通分量,而不只是强连通图.

那么我们先来思考一个问题:什么时候一个点u和它的子孙节点中的一部分构成强连通分量呢? 答案是:只要u的子孙节点再也没有指向u的祖先结点的有向边,而有指向u的有向边.我来解释一下这是为什么:因为只要u的子孙结点有指向u的祖先结点的有向边,那么就能构成一个更大的强连通图.为了方便理解,所以我再次举出一个图例.


图中(1,2,3,4)为强连通分量,而(2,3,4)中因为2的子结点指向了2的父节点1从而不符合强连通分量的概念,仅仅是一个强连通图.

但是u的子孙节点不一定都强连通呀,那么我们怎样才能在退回到u的时候知道有哪些点和u构成强连通分量呢?答案是维护一个栈.那么如何使用这个栈呢?如果在u之后被遍历到的点已经能与其下面的一部分点(也可能就只有他一个点)已经构成强连通分量,那么把它们一起从栈里弹出来就行了。所以最后回溯到点u的时候,如果u的子孙结点没有指向u的祖先结点的边,那么u之后的点肯定已经判断好是否联通了,所以就可以保证在栈中u和u之后的点是否能与u构成强连通分量.

可能这个过程比较抽象,所以我给出了一个例子方便理解

思路大概梳理完了,那么我们应该想一想怎样实现这个算法了:

为了实现tarjan算法,我们需要维护三个数组

    1) Dfn[i], 记录i是第几个被搜索到的

    2) Low[i], 记录i及其子孙节点的有向边所连的点中dfn[]最小的值

    3) InStack[i], 表示i是否在栈内


tarjan开始√

    step1: 初始化Dfn[i] = low[i] = ++deep;

    step2: 将当前结点cur入栈, InStack[cur] = 1;

    step3: 遍历u的所有出边,设抵达的下一个结点为v,如果v未曾被访问过(即Dfn[v] = 0),那么对v进行dfs, 之后更新Low[cur]的值,即Low[cur] = min{Lo[cur], Low[v]}.

    step4: 如果Dfn[cur] = Low[cur], 也就是说cur的子结点没有再指向cur的祖先结点, 那么它就构成了一个强连通分量, 将栈中cur和栈内cur之后的结点出栈, 这些结点就构成了一个强连通分量, 并给这些结点标记它们是第几个强连通分量中的结点, 最后将他们的InStack置0.

tarjan结束√

step4中我们为什么这么做呢,因为dfs肯定将cur后的结点都处理完了,也就是cur的子树中的强连通分量已经求完了, 自然u与剩下的结点就构成了强连通分量.

那么我们用一题模版题来结尾

洛谷OJ: P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm(强连通分量)

第二部分------缩点


第三部分------求割点、桥


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值