暑期总结-Tarjan算法

强连通分量是指有向图G里顶点间能互相到达的子图

即在这个子图中每个顶点直接或间接地连接。

Tarjan算法:规定一个数组dfn[i]记录第一次访问到i的时间,并将i入栈,然后low[i]记录该点所在的强连通子图所在搜索子树的根节点的Dfn值,又搜索子树中越靠前的dfn值越小,所以要尽量找小的dfn值。

伪代码:

tarjan(u)
{
    DFN[u]=Low[u]=++Index                // 为节点u设定次序编号和Low初值
    Stack.push(u)                        // 将节点u压入栈中
    for each (u, v) in E                 // 枚举每一条边
        if (v is not visted)             // 如果节点v未被访问过
            tarjan(v)                    // 继续向下找
            Low[u] = min(Low[u], Low[v])
        else if (v in S)                 // 如果节点v还在栈内
            Low[u] = min(Low[u], DFN[v])
    if (DFN[u] == Low[u])                // 如果节点u是强连通分量的根
        repeat 
            v = S.pop                    // 将v退栈,为该强连通分量中一个顶点
            print v
        until (u== v)
}

注意:由于一张图中可能有多个强连通分量,所以需要做多次tarjan操作。

tarjan求得之后,可以将同一强连通分量看作一个点,那么就可以得到一张有向无环图(DGA图),在有些题目中可以用到。

求强连通分量代码:

#include 
int n,m,first[10010],arraynum,strack[10010],top,in[10010],flag[10010];
int dfn[10010],low[10010],time,ans[10010],cont,js[10010];
struct ppp{
	int go,next;
}array[100010];
int min(int x,int y){
	if(xmax){
			max=js[i]; t=i;
		}
	}
	for(i=1;i<=n;i++){
		if(ans[i]==t) printf("%d ",i-1);//点的编号从0~N; 
	}
}




你可能感兴趣的:(暑期总结-Tarjan算法)