SCC

2024-04-10 03:18
文章标签 scc

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

注:大部分参见百度百科。

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

主要有三个算法。他们基于一个定理

定理在任何DFS中,同一SCC内的所有顶点均在同一棵深度优先树中。

该定理说明了强连通分量一定是有向图的某个深搜树子树。那么要找到一个分量,只要找到树根( 连接不同分量的桥的前端顶点) ,然后取出其所属分量的顶点即可。

1. Kosaraju算法(也就是clrs中的算法)   //时间代价O(E+V)

  step1:对原图G进行深度优先遍历,记录每个节点的离开时间。

  step2:选择具有最晚离开时间的顶点,对反图GT进行遍历,删除能够遍历到的顶点,这些顶点构成一个强连通分量。

  step3:如果还有顶点没有删除,继续step2,否则算法结束。

2. Tarjan算法:DFS+堆+标记      //时间代价O(E+V) 

根据白色路径引理,Tarjan确实能在线性时间内完成任务。

stack s;
graph G;
int dex;
tarjan(结点 u){
low(u) = dfu[u] = ++dex;       //dfu[i]为节点i搜索的次序编号,low[i]为i或i的子树能够追溯到的最早的栈中节点的次序编号
u入栈;
for (每一个 结点u 能到达的 结点v){
if( 没有被搜到){
tarjan(v);
low[u] = min(low[u],low[v]);
}
else 
low[u] = min(low[u],dfu[v]); 
}
if (low[u] == dfu[u])          //当dfu(i)=low(i)时,以i为根的搜索子树上所有节点是一个强连通分量。
出栈直到元素为u;                 //标记层数cnt,记录i所属连通分支SCC[i]均在这里操作
}

其一个实现参考博文《Poj-2186“Popular Cows” && poj2553"The Bottom of A Graph"》

3. Gabow算法:DFS+堆+堆         //时间代价O(E+V)

这个算法其实就是Tarjan算法的变异体,我们观察一下,只是它用第二个堆栈来辅助求出强连通分量的根,而不是Tarjan算法里面的 dfu[ ] 和 low[ ] 数组。那么,我们说一下如何使用第二个堆栈来辅助求出强连通分量的根。

我们使用类比方法,在Tarjan算法中,每次low[i]的修改都是由于环的出现(不然,low[i]的值不可能变小),每次出现环,在这个环里面只剩下一个low[i]没有被改变(深度最低的那个),或者全部被改变,因为那个深度最低的节点在另一个环内。那么Gabow算法中的第二堆栈变化就是删除构成环的节点,只剩深度最低的节点,或者全部删除,这个过程是通过出栈来实现,因为深度最低的那个顶点一定比前面的先访问,那么只要出栈一直到栈顶那个顶点的访问时间不大于深度最低的那个顶点。其中每个被弹出的节点属于同一个强连通分量。那有人会问:为什么弹出的都是同一个强连通分量?因为在这个节点访问之前,能够构成强连通分量的那些节点已经被弹出了,那么Tarjan算法中的判断根我们用什么来代替呢?其实就是看看第二个堆栈的顶元素是不是当前顶点就可以了。

其实Tarjan算法和Gabow算法其实是同一个思想的不同实现,但是,Gabow算法更精妙,时间更少(不用频繁更新low[ ])。

step1: 找一个没有被访问过的节点v,goto step2(v)。否则,算法结束。 
step2(v): 
将v压入堆栈stk1[]和stk2[] 
对于v所有的邻接顶点u: 
1) 如果没有访问过,则step2(u) 
2) 如果访问过,但没有删除,维护stk2[](处理环的过程) 
如果stk2[]的顶元素==v,那么输出相应的强连通分量

4. 总结:

Kosaraju算法的第二次深搜隐藏了一个拓扑性质,而Tarjan算法和Gabow算法省略了第二次深搜,所以,它们不具有拓扑性质。Tarjan算法用堆栈和标记,Gabow用两个堆栈(其中一个堆栈的实质是代替了Tarjan算法的标记部分)来代替Kosaraju算法的第二次深搜,所以只用一次深搜,效率比Kosaraju算法要高。

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



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

相关文章

SCC Tarjan算法

int dfs_clock,scc_cnt;int low[maxn],dfn[maxn],sccno[maxn]; //sccno[i]为i所在的SCC编号stack<int>S;vector<int>map[maxn];void tarjan( int u, int fa ){low[u] = dfn[u] = ++dfs_clock;S.push(u);for( int

SCC::poj2186 Popupar Cows poj2553 The Bottom of A Graph

关于SCC的知识与算法,参见《SCC》一文。这两道题本质是一样的,细微的区别只在于输出而已。夜鱼只给我做前一道题,大概是看到我做的《图算法》的小结里面没有SCC的地位,想给我提个醒。后来我在那篇小结里面补上了SCC,顺便也对SCC的知识梳理了一遍,觉得手痒,网上查了一下还有poj2553也是关于SCC的,但没想到poj2553一题是赤裸裸的SCC,但这道题我却WA了几次,原因是在输出的时候没有“按

BTP 连接SCC异常【Backend status could not be determined】

问题描述 一开始是CPI上使用RFC适配器访问后端系统出现异常,根据描述定位到可能是BTP和SCC的连接有问题 转到BTP查看与SCC的连接,发现无法连接到后端系统 解决方案 同事帮忙看了其他客户的BTP配置,BTP云连接器位置有两个实例,猜测因为多个实例导致无法定位到正确的后端系统。 翻了些SAP社区上的博客,提示这个问题可能和location ID未配置有关,转到目标Target页

阿里云GPU服务器命名规则gn、vgn、gi、f、ebm和scc详解

阿里云GPU服务器提供GPU加速计算能力,GPU卡支持A100、V100、T4、P4、P100、A10等,NVIDIA V100,GPU实例规格是什么意思?如搭载NVIDIA V100的ecs.gn6v-c8g1.2xlarge、A10卡ecs.gn7i-c32g1.8xlarge、T4卡ecs.gn6i-c4g1.xlarge、P4卡ecs.gn5i-c2g1.large、P100卡ecs.gn

SCC-Tarjan算法,强连通分量算法,从dfs到Tarjan详解

文章目录 前言定义强连通强连通分量 Tarjan算法原理及实现概念引入搜索树有向边的分类强连通分量的根时间戳追溯值 算法原理从深搜到TarjanTarjan算法流程Tarjan算法代码实现 OJ练习: 前言 强连通分量是图论中的一个重要概念,它在许多领域都有广泛的应用,如网络路由中识别环路,社交网络分析,编译器优化识别出代码中的循环结构,图像处理中识别出图像中的连通区域,从

HEVC-SCC rgb file input

关键字 csc allocateCSCBuffer()-> m_apcPicYuvCSC xCheckRDCostIntraCSC():更简单, enum ACTRDTestTypes {   ACT_TWO_CLR            = 0,  //two color space   ACT_TRAN_CLR           = 1,  //transformed color sp

U4_1:图论之DFS/BFS/TS/Scc

文章目录 一、图的基本概念二、广度优先搜索(BFS)记录伪代码时间复杂度流程应用 三、深度优先搜索(DFS)记录伪代码时间复杂度流程时间戳结构BFS和DFS比较 四、拓扑排序一些概念有向图作用拓扑排序 分析伪代码时间复杂度彩蛋 五、强连通分量-SCC分析伪代码时间复杂度 一、图的基本概念 由点(vertices)和边(edges)组成 G = ( V , E ) G=(V,E