Tarjan算法详解
目录
- 一、什么是强连通分量
- 1. 概念
- 2. 强连通分量
- 二、两种dfs遍历
- 1. 方式1
- 2. 方式2
- 三、一个简单例子理解算法
- 四、更完整的一个例子
- 五、Code实现
一、什么是强连通分量
tarjan强连通分量算法
1. 概念
连通:无向图中,从任意点i可到达任一点j
强连通:有向图中,从任意点i可到达任一点j
弱连通:把有向图看作无向图时,从任意点i可到达任一点j
- 如图,强连通无论那个点,都能按照方向到达任意一点,弱连通如果强行按方向,那么B到不了C,A到不了B和C,C到不了B。但如果把他看作是无向图,那么他们也能满足连通条件。
2. 强连通分量
整个图并不是强连通的,但是在某些局部区域,他确实也符合强连通的要求,如下图,整张图不算是强连通,但是局部还是能满足强连通条件的。
二、两种dfs遍历
1. 方式1
先访问当前节点,再递归相邻节点
- 如上图所示,先访问A,将A标记为已访问之后,我再去访问B,依次下去,B这个分支访问完了,再退回来dfs(F)。如果发现当前节点已经被访问过了,直接结束。因为既然已经被访问过了,那么他相邻的点必然也被访问过来,自然无需访问。
2. 方式2
先递归相邻节点,再访问当前节点
- 如上图所示,实际上就是顺序变了,有点像二叉树的后序遍历?对,就是后序遍历,这也是tarjan算法的核心。
三、一个简单例子理解算法
对于节点
x
,我有两个变量来表示他的信息,i
表示访问顺序(时间戳),j
表示按照方向进行访问,能够访问到的最早的节点的时间戳
如上,A的时间戳为1,B时间戳为2,C时间戳为3,D时间戳为4
A能访问到的最早的时间戳为1,B能访问到的最早的时间戳为2,C能先访问D,再访问到B所以最早时间戳也为2,D也是,能访问到的最早时间戳为2
有相同
j
值的节点构成一个强连通区域,如上图,B、C、D构成一个强连通区域,A自己构成一个强连通区域
四、更完整的一个例子
- 这里肯定会有人问,那我通过什么方法来更新
j
的值呢,这里我们可以根据打印顺序来进行寻找,先打印E
,E
只能访问到自己,于是E(5,5)
,然后打印D
,D
可以访问到B
,于是D(4,2)
,然后打印C
,C
能访问到D
,D
有最早时间戳2,于是C(2,2)
,然后再打印B
,B(2,2)
,然后开始DFS(F)
,说明之前的确实已经完成了打包了,B、C、D是一个强连通域,接着如上面步骤,找出AFG这个强连通域
五、Code实现
public class Main {static int time = 1;static Stack<Integer> stack = new Stack<>();static int[] dfn;//表示i属性static int[] low;//表示j属性static int n;//节点个数public static void main(String[] args) {n = 10;dfn = new int[n];//初始化low = new int[n];//初始化for (int i = 0; i < n; i++) {if (dfn[i] == 0) {DFS(i);}}}public static void DFS(int x) {stack.push(x);dfn[x] = time;low[x] = time;time++;for (int y = 0; y < n; y++) {if (x和y是连通的) {if (dfn[y] == 0) {//y这个节点没有被访问过DFS(y);low[x] = Math.min(low[x], low[y]);//更新最早时间戳} else if (如果y已经被访问过了,但是y在stack里面){low[x] = Math.min(low[x], low[y]);}}}if (dfn[x] == low[x]) {//如果我将他整个儿子都完成了遍历,结果他的访问时间戳和最早时间戳相等,说明我整个强连通分量的节点全部访问完了stack.pop();}}
}
Tarjan算法详解相关推荐
- Popular Cows POJ - 2186(tarjan算法)+详解
题意: 每一头牛的愿望就是变成一头最受欢迎的牛.现在有 N头牛,给你M对整数(A,B),表示牛 A认为牛B受欢迎.这种关系是具有传递性的,如果 A认为 B受欢迎, B认为 C受欢迎,那么牛 A也认为牛 ...
- Tarjan 算法详解
一个神奇的算法,求最大连通分量用O(n)的时间复杂度,真实令人不可思议.转自 废话少说,先上题目 题目描述: 给出一个有向图G,求G连通分量的个数和最大连通分量. 输入: n,m,表示G有n个点,m条 ...
- Tarjan算法详解(AcWing 1174 受欢迎的牛)
题目描述: 每一头牛的愿望就是变成一头最受欢迎的牛. 现在有 N 头牛,编号从 1 到 N,给你 M 对整数 (A,B),表示牛 A 认为牛 B 受欢迎. 这种关系是具有传递性的,如果 A 认为 B ...
- tarjan算法详解--图论--强连通图
目录 1.有向图连通性(强连通图) 1.1有向图 1.2有向图连通性 2.tarjan算法简述 3.实现过程 3.1 例题-刻录光盘 3.1.1 输入&&初始化 3.1.2 tarja ...
- Tarjan(塔杨)算法详解
Tarjan算法详解 前言 简介 教学代码-有向图的强联通分量 教学代码-点双联通分量 教学代码-边双联通分量 实战代码-边双 实战代码-点双 前言 Tarjan(塔杨)算法其实不是很复杂,对于图这一 ...
- Matlab人脸检测算法详解
这是一个Matlab人脸检测算法详解 前言 人脸检测结果 算法详解 源代码解析 所调用函数解析 bwlabel(BW,n) regionprops rectangle 总结 前言 目前主流的人脸检测与 ...
- 图论-最短路Dijkstra算法详解超详 有图解
整体来看dij就是从起点开始扩散致整个图的过程,为什么说他稳定呢,是因为他每次迭代,都能得到至少一个结点的最短路.(不像SPFA,玄学复杂度) 但是他的缺点就是不能处理带负权值的边,和代码量稍稍复杂. ...
- C++中的STL算法详解
1.STL算法详解 STL提供能在各种容器中通用的算法(大约有70种),如插入.删除.查找.排序等.算法就是函数模板,算法通过迭代器来操纵容器中的元素.许多算法操作的是容器上的一个区间(也可以是整个容 ...
- 粒子群(pso)算法详解matlab代码,粒子群(pso)算法详解matlab代码
粒子群(pso)算法详解matlab代码 (1)---- 一.粒子群算法的历史 粒子群算法源于复杂适应系统(Complex Adaptive System,CAS).CAS理论于1994年正式提出,C ...
- 基础排序算法详解与优化
文章图片存储在GitHub,网速不佳的朋友,请看<基础排序算法详解与优化> 或者 来我的技术小站 godbmw.com 1. 谈谈基础排序 常见的基础排序有选择排序.冒泡排序和插入排序.众 ...
最新文章
- 专业软件测试面试题汇总
- grep搜索带有特殊符号的规律
- python selenium 等待页面加载_python selenium 三种等待方式详解(实战常用)
- webservice xml java_java访问WebService接口返回xml
- oracle错误12637,TNS-12537 TNSconnection closed ORA-609错误处理
- python两数相乘代码_Python 实现大整数乘法算法的示例代码
- springboot属性注入转化为对象
- python结束线程类_Python线程指南(转)
- oracle 的 父子关系,oracle父子关系树递归排序要注意什么?
- 【Flutter】Dart数据类型之num
- pyspark分类算法之梯度提升决策树分类器模型GBDT实践【gradientBoostedTreeClassifier】
- 转 VSS 2005 使用详解
- 通达\铭心联手,共探企业信息化营销新机遇
- 智慧城管管理平台和监控系统建设方案
- php未来发展前景如何
- 小游戏 版本提交审核, 资质提交审核指引
- 《拆掉思维里的墙》—— 读后总结
- TensorFlow Lite(实战系列一):TFLite Android 迁移训练构建自己的图像识别APP
- 前端笔记(03)——一文看懂flex布局
- 留个档,C# AlphaBlend,带Alpha通道的图片的叠加