有向图算法流程展示
从节点1开始DFS,把遍历到的节点加入栈中。搜索到节点u=6时,DFN[6]=LOW[6],找到了一个强连通分量。退栈到u=v为止,{6}为一个强连通分量。
返回节点5,发现DFN[5]=LOW[5],退栈后{5}为一个强连通分量。
返回节点3,继续搜索到节点4,把4加入堆栈。发现节点4像节点1的后向边,节点1还在栈中,所以LOW[4]=1。节点6已经出栈,不再访问6,返回3,(3,4)为树枝边,所以LOW[3]=LOW[4]=1。
继续回到节点1,最后访问节点2。访问边(2,4),4还在栈中,所以LOW[2]=4。返回1后,发现DFN[1]=LOW[1],把栈中节点全部取出,组成一个连通分量{1,3,4,2}。
2返回1时low归为1,弹出1,因此栈中的数全部弹出
至此,算法结束。经过该算法,求出了图中全部的三个强连通分量{1,3,4,2},{5},{6}。
void tarjan(int x){
dfn[x]=low[x]=++num;//low指能到达的最早点的时间戳,dfn打上时间戳
s[++p]=x;v[x]=1;//s[]为栈 v[]是否在栈中
for(int i=head[x];i;i=next[i]){
if(!dfn[ver[i]]){//ver[]为下一个点//如果ver[i]没有处理过
tarjan(ver[i]);//处理ver[i]
low[x]=min(low[x],low[ver[i]]);//树枝边
}//if
else if(v[ver[i]]) low[x]=min(low[x],dfn[ver[i]]);//返祖边
if(low[x]==dfn[x]){
int y;++t;//t记录强联通分量的个数
while(y!=x){y=s[p--];v[y]=0;c[y]=t;}//弹出
}//if
}//for
}//void