tarjan算法介绍与分析

2024-05-04 06:38
文章标签 算法 分析 介绍 tarjan

本文主要是介绍tarjan算法介绍与分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  tarjan算法是一个求取有向图的所有强连通分量的算法,它是以算法提出者Robert Tarjan的名字来命名的。提出此算法的Robert Tarjan是普林斯顿大学的教授,同时他也是1986年的图灵奖获得者(图灵奖是计算机领域的最高荣誉,和物理、化学领域的诺贝尔奖是一个层次的奖项)。
  在详细讲述该算法之前,我们需要明确几个概念(注意该算法的研究对象是有向图,无向图没有强连通等概念)。
1. 强连通
  如果两个顶点可以互相通达,则称这两个顶点强连通。
2. 强连通图
  如果有向图G中的任意两个顶点都是强连通的,那么我们称该有向图G是强连通图。
3. 强连通分量
  非强连通图的极大强连通子图称为强连通分量。
  例如Graph 1就是一个强连通图,Graph 2 不是强连通图,因为4节点不存在到1、2和3的路径。
        强连通图非强连通图
  
  下面介绍该算法的处理流程:
1. 首先定义两个数组dfn和low,其中dfn用于记录dfs(深度优先搜索)时,当前节点u的访问时间戳,这里用计数器实现。low用于记录以当前节点u作为根节点能达到的最短时间戳,因为如果出现回边,此时的low值就可能会变小。
2. 初始化时,令节点u的dfn和low值为当前的时间戳count。
3. 如果当前节点u有相连的节点v,此时分为以下几种处理情况。
  - v节点未访问过,此时直接递归处理v。递归返回时low[u]=min{low[u],low[v]}。
  - v节点已访问过且v已和其它节点构成了一个连通分量,即v不在栈中,此时(u,v)为横叉边,不做任何处理。
  - v节点已访问过且v在栈中,此时(u,v)是回边,low[u]=min{low[u],dfn[v]}。注意v节点由于仍在栈中,所以其low[v]的最终值还不确定,当然low[v]总是小于等于dfn[v]的,因此二者都行。
4. 当u节点的所有连接边处理完毕时,low[u]的值也就确定了。此时比较dfn[u]和low[u]的值,若二者相同,则说明栈中从该节点往上的所有节点构成一个强连通分量,将其弹出即可。要理解这个判定规则的原理,需要明确dfn和low的定义,这里dfn[u]表示节点u第一次访问时的时间戳,low[u]是u的子节点能达到的最小时间戳,若u无子节点,则low[u]等于dfn[u],即u节点自身构成一个强连通分量。
5. 需要注意的是当我们处理完一个强连通分量时,有可能需要改变搜索的起点,因此我们可以在外围添加一个循环,若某个节点未访问过,则调用1-4步骤进行处理。
  
  以下是该算法的伪代码描述。

tarjan(u) 
{dfn[u]=low[u]=++count               // 为节点u设定时间戳dfn和low初值stack.push(u)                       // 将节点u压入栈中for each (u, v) in E                // 枚举u的每一条出边if (v is not visited)           // 如果节点v未被访问过tarjan(v)                   // 递归向下处理low[u] = min(low[u], low[v])else if (v in S)                // 如果节点v还在栈内low[u] = min(low[u], dfn[v])if (dfn[u] == low[u])               // 如果节点u是强连通分量的根repeatv = stack.pop               // 将v出

这篇关于tarjan算法介绍与分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/958551

相关文章

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

zookeeper端口说明及介绍

《zookeeper端口说明及介绍》:本文主要介绍zookeeper端口说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、zookeeper有三个端口(可以修改)aVNMqvZ二、3个端口的作用三、部署时注意总China编程结一、zookeeper有三个端口(可以

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

Python中win32包的安装及常见用途介绍

《Python中win32包的安装及常见用途介绍》在Windows环境下,PythonWin32模块通常随Python安装包一起安装,:本文主要介绍Python中win32包的安装及常见用途的相关... 目录前言主要组件安装方法常见用途1. 操作Windows注册表2. 操作Windows服务3. 窗口操作

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

python中Hash使用场景分析

《python中Hash使用场景分析》Python的hash()函数用于获取对象哈希值,常用于字典和集合,不可变类型可哈希,可变类型不可,常见算法包括除法、乘法、平方取中和随机数哈希,各有优缺点,需根... 目录python中的 Hash除法哈希算法乘法哈希算法平方取中法随机数哈希算法小结在Python中,

Java Stream的distinct去重原理分析

《JavaStream的distinct去重原理分析》Javastream中的distinct方法用于去除流中的重复元素,它返回一个包含过滤后唯一元素的新流,该方法会根据元素的hashcode和eq... 目录一、distinct 的基础用法与核心特性二、distinct 的底层实现原理1. 顺序流中的去重