强连通分量由美国计算机科学家 Robert Tarjan 提出。
Tarjan
职业:计算机科学家
主要成就:设计了求解的应用领域的许多问题的广泛有效的算法和数据结构等,1986年获得图灵奖.
简介:Robert Tarjan,计算机科学家,以LCA、强连通分量等算法闻名。他拥有丰富的商业工作经验,1985年开始任教于普林斯顿大学。
事实上上述并没有什么用。如果真的想知道就上百度百科吧。
分割线
普及几个强连通分量的定义
强连通: 在一个有向图G里,设两个点 a b 发现,由a有一条路可以走到b,由b又有一条路可以走到a,我们就叫这两个顶点(a,b)强连通
强连通图: 如果 在一个有向图G中,每两个点都强连通,我们就叫这个图为强连通图。
强连通分量:在一个有向图G中,有一个子图,这个子图每2个点都满足强连通,我们就叫这个子图叫做 强连通分量
1.现在是有向图的Tarjan。
先来看个图。
由上述定义知:
子图1,2,3构成一个强连通。
点4独立为一个强连通。
点5也是一个独立的强连通。
相信现在的你已经知道强连通分量究竟是什么了。
然而一个重要的问题产生了:
怎么求它呢???
dfs
那么怎么dfs呢?
首先需要三个数组:
1.dfn[Max];(存储时间戳)
2.low[Max];(存储在它之前的最小时间戳)
3.cast[Max];(标记它所在的强连通)
还是刚才的图。
开始时dfn==low;
从1开始(入栈),先搜点2(入栈);
点2再搜点3(入栈),点3搜到了点1,这是点1正在栈中(更新点3的low值;
回溯更新点2的low,再回溯更新点1的low(当然还是原来的low,点1的dfn==low;
此时1搜到4(入栈),点4搜到点5;
点5开始纠结,因为他搜不到别人了,只好老老实实的被使用自己的low;
于是点5的dfn==low成为了一个强连通(出栈);cast[5]=1;
点4也由于点5的low影响不到他,dfn==low,也成为了一个强连通(出栈)。cast[4]=2;
回溯到点1,发现点5已经被访问,而且已经出栈,便不用理他。
此时dfn[1]==low[1]。
开始大批出栈
1出栈,2出栈,3出栈。cast全为3;
成功
那么看一段代码吧:
void tarjan(int x)
{
s.push(x);
ins[x]=1;
inx++;
dfn[x]=low[x]=inx;
for(int i=head[x];i!=-1;i=e[i].next)
{
if(dfn[e[i].to]==0)
{
tarjan(e[i].to);
low[x]=min(low[x],low[e[i].to]);
}
else if(ins[e[i].to]==1)low[x]=min(low[x],dfn[e[i].to]);
}
int v=100000;
if(dfn[x]==low[x])
{
gs++;
while(x!=</