首页 > 编程语言 >Tarjan算法与连通性相关(一)

Tarjan算法与连通性相关(一)

时间:2024-08-02 14:50:41浏览次数:11  
标签:结点 连通性 连通 Tarjan 算法 dfn low 分量

昨天在打牛客多校的时候遇到了一道与连通性有关的图论题,笔者一眼就看出这题考察的知识点是Tarjan算法,但是笔者上次写Tarjan算法还是三年前的事情(太惭愧了qaq),于是笔者和队友在赛时花了一个小时时间学习了Tarjan算法成功通过了此题,故写下这篇博客进一步加深印象,同时也是分享自己对于该算法的理解

什么是Tarjan算法?

Tarjan是一位伟大的美国计算机科学家的名字,他发明了许多好用的算法和数据结构,以他的名字命名,这里我们主要介绍的是与连通性有关的Tarjan算法

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

什么是强连通分量?

首先我们要知道强连通的概念:有向图 G 强连通是指,G 中任意两个结点连通,换句话说就是 G 中任意两个结点可以相互到达,强连通分量指的是从这张有向图中选出一个最大的子图,使得这张子图是强连通的

怎么求强连通分量?

在介绍Tarjan算法求强连通分量前,首先我们要知道一个很重要的概念叫DFS生成树,如图所示:

这颗树是在我们进行DFS的过程中,按照搜索的顺序遍历过程中生成的一颗树,我们会发现这颗树上有4种不同颜色的边:

1.树边(黑色边):每次搜索到一个还未被访问的结点形成的边

2.返祖边(红色边):指向祖先结点的边

3.横叉边(蓝色边):搜索的过程中遇到一个已经访问过的结点形成的边,但该点不是当前结点的祖先

4.前向边(绿色边):搜索过程中遇到子树中的结点形成的边

为什么我们要在这里介绍DFS生成树呢?

我们观察树的结构发现,对于属于某一个强连通分量的结点u,如果在搜索树中它是所在强连通分量第一个被遍历到的点,那么该强连通分量中的剩余点一定在以u为根的子树中,这个性质对我们求出强连通分量具有重要的作用

学习完搜索树后,我们终于可以开始介绍Tarjan算法求有向图强连通分量了

Tarjan算法是基于对图进行深度优先搜索,我们视每个连通分量为搜索树中的一棵子树,在搜索过程中,维护一个栈,每次把搜索树中尚未处理的节点加入栈中

在算法的过程中我们需要维护几个变量:

dfn[u]: u 的dfs是序,即在DFS的过程中结点 u 被搜索到的次序

low[u]:在 u 的子树中能够回溯到的最早的已经在栈内的点

我们观察树的结构,很自然能够发现,对于一个强连通分量内的点,它的 low 值要么等于该强连通分量的根结点的 dfn 值,要么是该强连通分量通过一条边
能够到达的结点的 dfn 值

进一步的,我们可以发现对于一颗子树,子树中其它结点的 dfn 值一定会大于根结点的 dfn 值;同时,子树中结点的 low 值一定不小于根结点的 dfn 值

那么维护这两个变量有什么用呢?

我们注意到刚才上面加粗的那句话,很自然能够想到:对于一个强连通分量,有且只有根结点的 dfn 值会等于 low 值,所以我们考虑把当前搜索到的元素加入到一个栈中,不断弹出栈中元素,直到找到 dfn 值和 low 值相等的结点,那么这些点就是以这个 dfn 值和 low 值 相等的点为根的一个强连通分量

所以现在我们的瓶颈就在于如何维护 dfn 和 low 的信息

在搜索的过程中,我们考虑当前的结点 u 以及与它相连的结点 v ,一共有三种情况:

  1. v 未被访问过:继续对 v 进行dfs,在回溯过程中用 low[v] 更新 low[u] ,因为 u 和 v 之间存在连边,所以 v 能够回溯到的点, u 一定能回溯到

  2. v 被访问过且在栈中,那么 \(low[u] = min(low[u],dfn[v])\)

  3. v 被访问过且不在栈中,那么说明 v 所在的强连通分量已经被处理,不需要进行操作

综上所述,我们就能够在 \(O(n+m)\) 的时间复杂度内求出强连通分量了

代码如下:

int dfn[N],low[N],dfncnt,s[N],in_stack[N],tp;
int scc[N],sc;
int sz[N];
vector<int> g[N];
void tarjan(int u){
	low[u]=dfn[u]=++dfncnt,s[++tp]=u,in_stack[u]=1;
	for(auto v:g[u]){
		if(!dfn[v]){
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else {
			if(in_stack[v])
				low[u]=min(low[u],dfn[v]);
		}
	}
	if(dfn[u]==low[u]){
		++sc;
		while(s[tp]!=u){
			scc[s[tp]]=sc;
			sz[sc]++;
			in_stack[s[tp]]=0;
			--tp;
		}
		scc[s[tp]]=sc;
		sz[sc]++;
		in_stack[s[tp]]=0;
		tp--;
	}
}

标签:结点,连通性,连通,Tarjan,算法,dfn,low,分量
From: https://www.cnblogs.com/isletfall/p/18338743

相关文章

  • 数据结构与算法-二分搜索树节点的查找
    ......
  • 解密编程的八大法宝(三)(附贪心算法、动态规划和字符串匹配算法详解)
    算法题中常见的几大解题方法有以下几种:暴力枚举法(BruteForce):这是最基本的解题方法,直接尝试所有可能的组合或排列来找到答案。这种方法适用于问题规模较小的情况,但在大多数情况下效率不高。贪心算法(GreedyAlgorithm):贪心算法在每一步都选择当前看起来最优的解,希望最终能......
  • Day 31 贪心算法 Part05
    56.合并区间区间这类问题,不是按照左端点排序就是按照右端点排序,在思考思路的时候,就从这两个方向去下手,然后再去想贪心,以及从左侧开始遍历还是右侧开始遍历。classSolution{publicint[][]merge(int[][]intervals){if(intervals.length==1)returninterva......
  • 一文读懂CST电磁仿软件的TLM算法原理和历史背景
    这期我们免公式地介绍一下TLM原理。TLM(TransmissionLineMethod)是传输线矩阵算法,基于Huygens的波传播模型的三维全波电磁算法,注意是fullwave哦!什么是Huygens原理?惠更斯原理能准确计算波的传播。简单讲就是波传播的最前沿(wavefront)上每个点都可以看作是下一时刻的波的点源。......
  • 代码随想录算法训练营第二十一天| 39. 组合总和, 40.组合总和II, 131.分割回文串
    今天是回溯算法学习的第二天,主要的学习内容包括:1.组合问题的重复使用2.组合问题的去重3.分割问题的处理方法。39.组合总和题目链接:39.组合总和-力扣(LeetCode)这个组合问题的特点是,集合内的元素可以重复使用。与前面组合问题的区别在于,在每一次回溯中,不是从i+1的位置开......
  • 数组算法
    数组的算法目录数组的算法搜索方法排序方法排序算法库搜索方法线性搜索(LinearSearch):算法:遍历数组,直到找到目标值或遍历完数组。时间复杂度:O(n)。应用:在未排序的数组中查找元素。publicintlinearSearch(int[]arr,inttarget){for(inti=0;i<arr.......
  • 代码随想录算法训练营第57天 | 并查集理论基础
    并查集理论基础https://www.programmercarl.com/kamacoder/图论并查集理论基础.html107.寻找存在的路径https://kamacoder.com/problempage.php?pid=1179代码随想录https://www.programmercarl.com/kamacoder/0107.寻找存在的路径.html#思路并查集理论基础并查集用于判断......
  • 数组的算法
    数组的算法常见排序算法主要有:冒泡排序,选择排序,计数排序,基数排序,堆排序,桶排序,归并排序,希尔排序,插入排序,快速排序等等。冒泡排序(BubbleSort):两个for循环(外面的遍历数组,数组最后个元素不用遍历,因为要两两比较。里面的进行两两比较)通过重复遍历要排序的数列,比较每对相邻......
  • 解密编程的八大法宝(四)(附二分查找、分治法和图论算法(深度和广度优先搜索、最短路径、最
    算法题中常见的几大解题方法有以下几种::暴力枚举法(BruteForce):这是最基本的解题方法,直接尝试所有可能的组合或排列来找到答案。这种方法适用于问题规模较小的情况,但在大多数情况下效率不高。贪心算法(GreedyAlgorithm):贪心算法在每一步都选择当前看起来最优的解,希望最终能......
  • 深入理解PHP数组反转的算法
    本文由ChatMoney团队出品在PHP开发中,数组反转是一个常见的操作,它涉及到将数组的键值对或者键的顺序进行倒序排列。本文将深入探讨PHP数组反转的算法,并提供相应的代码示例。一、PHP数组反转基础在PHP中,数组反转通常涉及到两个函数:array_reverse()和array_flip()。......