在此大概讲一下初学Tarjan算法的领悟( QwQ)

Tarjan算法 是图论的非常经典的算法 可以用来寻找有向图中的强连通分量 与此同时也可以通过寻找图中的强连通分量来进行缩点

首先给出强连通分量的定义:

若在有向图G中 存在u到v的路径的同时也存在v到u的路径 则称u与v是强连通的 若G中所有点之间两两之间是强连通的则称G为一个强连通图 一个有向非强连通图极大强连通子图称为强连通分量

极大强连通子图:G是一个极大强连通子图 当且仅当G是一个强连通图 同时不存在另一个强连通图G'使G是它的真子集

下面 的2 3 4 三个点构成一个强连通分量 同时1也是一个强连通分量

通过观察强连通分量的定义我们可以发现 如果通过dfs遍历含有强连通分量的图 一个点可能与它的子节点在同一个强连通分量中 或者与父节点在同一个强连通分量 若点V延伸出的dfs搜索树中有节点跟V有连边就意味着这个节点回溯回来的路径上的所有点与V强连通 同时点V延伸的搜索树中不一定只有一个节点满足这样的条件 而当把这样的节点找全以后 就求出了以V节点为根节点的搜索树中所有与V强连通的点

但是这样操作并没有考虑V的父节点或祖父节点即此时求得的并不一定是一个强连通分量只能说明这些点强连通 但最终一定能求出包含dfs起点的强连通分量(以dfs起点为根节点的搜索树中必定包含所有与起点强连通的点

但若要求求出所有强连通分量 则不管算法的时间复杂度 求出整张图的强连通分量需要暴力枚举每一个点才能得到所有强连通分量 而这样时间复杂度会达到n2 级别

看起来不错但操作过于暴力所以让我们想一想有没有更好的做法?在遍历V的搜索树时 它的子节点不仅可能有边连接V 还可能连接到V的父节点或祖先节点或其他与V强连通的点 有没有什么方法能够利用这一点来简化算法?或者怎样唯一确定V是一个强连通分量的根节点?(确定一个点V 而所有与V强连通的点在以V为节点的搜索树中

若以1点为dfs起点可以求出包含1的强连通分量 但不能在搜索完以2点为根节点的搜索树时判断2是否是一个强连通分量的根节点

接下来正式开始介绍Tarjan算法:

Tarjan算法基于dfs

强连通分量在dfs中的根节点延伸的搜索树中包含所有与根节点强连通的点(废话)

强连通分量是由环构成(废话*2)

那么一个点V是一个强连通分量的根节点的条件是在它的搜索树中没有节点能访问到它的父节点或祖先 否则V可与它的父亲或祖先节点构成一个环故与V强连通的点的集合属于与V的父亲或祖父节点强连通的点的集合 同时点V若与它的祖父节点或父节点相连 那么它的祖父或父亲节点所在强连通分量的根节点显然与点V所在的强连通分量的根节点相同

再然后在dfs搜索的过程中搜索与回溯的过程相当于一个栈而子节点在栈中永远在父节点的上方 那么一个强连通分量的根节点在栈中时也必然在与它所有强连通的点的下方 而平时回溯时会直接退栈而我们在回溯时判断此时的节点是不是强连通分量的根节点 将当前点和在当前点之上的所有点取出 这些点共同构成一个强连通分量 不是 则保留栈中节点

因为一个节点若不是强连通分量的根节点 那由它搜索下去必定与栈中的某个节点V'之间所有的节点构成一个环而环上所有点之间强连通 又因为强连通分量的根节点在栈中必然在与它所有强连通的点下方故V'便是此时这个节点所在强连通分量的根节点 而且由以上操作可知留在栈中的点属于某个以栈中某个点为根节点的强连通分量 同时由dfs特性知回溯到某个强连通分量的根节点时栈中在它之上的点不可能属于此根节点之下的强连通分量否则说明该节点不是根节点因为它的子节点可以与父节点或祖先节点相连

具体代码实现时可以维护一个Low[V]  Low[V]记录的是V所属于的强连通分量的根节点的dfs序  由dfs序可知强连通分量的根节点的dfs序是整个强连通分量中最小的 那么搜索完后只需要判断Low[V]是否等于V的dfs序即可知V是否为强连通分量的根节点 而显然Low[V]=min(Low[to],Low[V]),to∈V的子节点 而当V连接的是已经在栈中的点V'时则Low[V]=min(Low[V],V'的dfs序) 

算法时间复杂度:

显然Tarjan算法中每一点都只会进栈一次出栈一次 而每一个节点都会遍历它的所有边 故Tarjan算法求有限图中的强连通分量的时间复杂度为T(n+m)

代码以后补齐:

Tarjan算法初探 (1):Tarjan如何求有向图的强连通分量的更多相关文章

  1. 图论-求有向图的强连通分量(Kosaraju算法)

    求有向图的强连通分量     Kosaraju算法可以求出有向图中的强连通分量个数,并且对分属于不同强连通分量的点进行标记. (1) 第一次对图G进行DFS遍历,并在遍历过程中,记录每一个点的退出顺序 ...

  2. Tarjan算法 求 有向图的强连通分量

    百度百科 https://baike.baidu.com/item/tarjan%E7%AE%97%E6%B3%95/10687825?fr=aladdin 参考博文 http://blog.csdn ...

  3. Tarjan算法求有向图的强连通分量

    算法描述 tarjan算法思想:从一个点开始,进行深度优先遍历,同时记录到达该点的时间(dfn记录到达i点的时间),和该点能直接或间接到达的点中的最早的时间(low[i]记录这个值,其中low的初始值 ...

  4. tarjan算法(割点/割边/点连通分量/边连通分量/强连通分量)

    tarjan算法是在dfs生成一颗dfs树的时候按照访问顺序的先后,为每个结点分配一个时间戳,然后再用low[u]表示结点能访问到的最小时间戳 以上的各种应用都是在此拓展而来的. 割点:如果一个图去掉 ...

  5. (转)求有向图的强连通分量个数(kosaraju算法)

    有向图的连通分量的求解思路 kosaraju算法 逛了很多博客,感觉都很难懂,终于找到一篇能看懂的,摘要记录一下 原博客https://www.cnblogs.com/nullzx/p/6437926 ...

  6. 【数据结构】DFS求有向图的强连通分量

    用十字链表结构写的,根据数据结构书上的描述和自己的理解实现.但理解的不透彻,所以不知道有没有错误.但实验了几个都ok. #include <iostream> #include <v ...

  7. 求有向图的强连通分量个数 之 Kosaraju算法

    代码: #include<cstdio> #include<cstring> #include<iostream> using namespace std; ][] ...

  8. Tarjan算法初探(2):缩点

    接上一节 Tarjan算法初探(1):Tarjan如何求有向图的强连通分量 Tarjan算法一个非常重要的应用就是 在一张题目性质在点上性质能够合并的普通有向图中将整个强连通分量视作一个点来把整张图变 ...

  9. 图->连通性->有向图的强连通分量

    文字描述 有向图强连通分量的定义:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly co ...

随机推荐

  1. Android设备网络、屏幕尺寸、SD卡、本地IP、存储空间等信息获取工具类

    Android设备网络.屏幕尺寸.SD卡.本地IP.存储空间.服务.进程.应用包名等信息获取的整合工具类. package com.qiyu.ddb.util; import android.anno ...

  2. angularjs -- 监听angularJs列表数据是否渲染完毕

    前端在做数据渲染的时候经常会遇到在数据渲染完毕后执行某些操作,这几天就一直遇到在列表和表格渲染完毕后,执行点击和选择操作.对于angularjs处理这类问题,最好的方式就是指令 directive. ...

  3. 网络 互联网接入方法、Mbit与MB的转换

    ADSL:非对称数字用户环路(绝大多数家庭接入方法,使用电话线).可以提供最高1Mbps的上行速率和最高8Mbps的下行速率.最新的ADSL2+可以提供最高24Mbps的下行速率. 千千兆TB 千兆G ...

  4. Object、String、数组的 toString() 方法和 equals() 方法及java.util.Arrays

    public class Test { public static void main(String[] args) { int[] a = {1, 2, 4, 6}; int[] b = a; in ...

  5. 【AOP】spring 的AOP编程报错:[Xlint:invalidAbsoluteTypeName]error

    AOP来发过程中,报错如下: warning no match for this type name: net.shopxx.wx.institution.controller [Xlint:inva ...

  6. JSP中forEach和forTokens循环的用法

    <%@page import="java.util.*"%> <%@ page language="java" contentType=&qu ...

  7. C#.net XML的序列化与反序列化

    /// <summary> /// 将一个对象序列化为XML字符串 /// </summary> /// <param name="o">要序列 ...

  8. 铁乐学python_day23_面向对象进阶1_反射

    铁乐学python_day23_面向对象进阶1_反射 以下内容大部分摘自博客http://www.cnblogs.com/Eva-J/ isinstance()和issubclass() 两者的返回值 ...

  9. C盘下出现msdia80.dll文件

    删除方法 https://jingyan.baidu.com/article/63acb44acef55661fdc17e56.html 或者 https://www.cnblogs.com/ggll ...

  10. JAVA容器全面总结

    1      容器体系图 简图: 详图: 2      基础 2.1      Iterator接口 迭代器. 具有的能力:后向迭代.删除. 2.2      Iterable接口 表示一个类具有迭代 ...