【点击领取】阿里云代金券 | 阿里云优惠券 |阿里云优惠码|云服务器|阿里云|阿里云代金券 – 限时领取1888元阿里云代金券
html
【3折购买ECS服务器入口】https://promotion.aliyun.com/ntms/act/qwbk.html?userCode=t9686fzw
数组
【9块9云服务 学生计划】https://promotion.aliyun.com/ntms/act/campus2018.html?userCode=g6nivc1vbash
强连通定义:在有向图G<V,E>中,对于点集V'∈V, 点集中的任意两点均可达,则称V'为强连通。 服务器
孤立的一个点也是一个强连通份量 post
在嵌套的多个环时 : {全部环上的点}为一个强连通份量( 最小环就是每一个孤立点)注意必定是知足条件的最大点集。阿里云
则上图中强连通份量有 {1},{2},{3},{7},{4,5,6} url
------------------------------------
spa
tarjan的过程就是dfs过程3d
对图dfs一下,遍历全部未遍历过的点 ,会获得一个有向树,显然有向树是没有环的。(注意搜过的点不会再搜)code
则能产生环的 只有(指向已经遍历过的点)的边
如左图,只有红色与绿色边有可能产生环。
对于深搜过程,咱们须要一个栈来保存当前所在路径上的全部点(栈中全部点必定是有父子关系的)
再仔细观察红边与绿边,首先获得结论:红边不产生环,绿边产生环
一、对于红边,链接的两个点三、7没有父子关系,这种边称为横叉边。 横叉边必定不产生环。
二、对于绿边,链接的两个点六、4是父子关系,这种边称为后向边。 环必定由后向边产生。
三、图中除了黑色的树枝边,必定只有横叉边和后向边(不存在其余种类的边)
------------------------------------
则如下考虑对于这两种边的处理和判断:
首先深搜会搜到这样的图:
Stack = {1,2,3},3没有多余的其余边,所以3退栈,把3做为一个强连通份量
------------------------------------
再次深搜:
此时栈 Stack = {1,2,7}
发现红边指向了已经遍历过的点3 => 是上述的2种边之一
而3不在栈中 => 3点与7点无父子关系
=> 该边为横叉边
=>采起无视法。
继而7点退栈 产生连通份量{7}
继而2点退栈 产生连通份量{2}
------------------------------------
再次深搜:
此时 Stack = {1,4,5,6}
发现绿边指向了已经遍历过的点4 => 是上述的2种边之一
而4在栈中 => 4点与6点是父子关系
=> 该边为后向边
=>4->6的路径上的点都是环。
int num[N], Top = 0;
int u = Stack.top();
while(u!=4){ num[Top++] = u; Stack.pop(); u = Stack.top();}
num[Top++] = u;
复制代码
如此就能把Stack中 4->6路径上的点转移到num数组里
显然num数组中的点是一个连通份量。
------------------------------------
实际状况可能更复杂:
出现了大环套小环的状况,显然咱们认为最大环是一个强连通份量(即:{4,5,6,8} )
于是咱们须要强化一下dfs过程:
定义:
int Time, DFN[N], Low[N]; DFN[i]表示 遍历到 i 点时是第几回dfs
Low[u] 表示 以u点为父节点的 子树 能链接到 [栈中] 最上端的点 的
DFN值(换句话说,是最小的DFN,由于最上端的DFN是最小的嘛)
int Stack[N], top; //上述的栈
【点击领取】阿里云代金券 | 阿里云优惠券 |阿里云优惠码|云服务器|阿里云|阿里云代金券 – 限时领取1888元阿里云代金券
【3折购买ECS服务器入口】https://promotion.aliyun.com/ntms/act/qwbk.html?userCode=t9686fzw
【9块9云服务 学生计划】https://promotion.aliyun.com/ntms/act/campus2018.html?userCode=g6nivc1v