关于强连通分量的一些理解(tarjan版本)

------------------------------------------概念部分----------------------------------------------------------------

强连通是在有向图当中提出的概念,代表点点之间都可以互相达到

下面说几个具体的概念:

顶点强连通:在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected)。

强连通图:如果有向图G的每两个顶点都强连通,则称G是一个强连通图。

强连通分量:非强连通图有向图的极大强连通子图,成为强连通分量(strongly connected components)。

---------------------------------------算法部分-------------------------------------------------------------------- 

利用tarjan算法求解强连通分量。

定义两个数组dfn[]和low[],dfn[]代表某个点的深搜序的时间戳,low[]代表当前点及其子树中的点能够直接连接到点的最小的时间戳。我们还需要一个栈去存储每个被访问到的点。low和dfn数组的维护方法就是标准的tarjan算法的维护方法。

那么我们如何得到强连通分量呢?

当low[u] == dfn[u]的时候,证明u的子树当中的点(包括它本身),不存在连向子树以外的点,那么也就是这个子树当中的点是一个强连通分量。如果能够连向子树以外的点,那么当前点能够在深搜的路径中到达,也可以通关过反向的这条边返回这条边,依旧保证了强连通的性质,当这种性质不存在的时候,那么当前的连通子图是最大的,也就是强连通分量。此时位置在栈的上面的点均是在当前子树中的,那么我们利用栈的性质,我们就能够得到这个强连通分量当中所有的点

--------------------------------------代码模板部分------------------------------------------------------------------

这个模板是测过的,我保证..........

void tarjan ( int u )  
{  
    dfn[u] = low[u] = ++times;  
    mark[u] = 1;  
    s.push ( u );  
    int len = e[u].size();  
    for ( int i = 0 ; i < len ; i++ )  
    {  
        int v = e[u][i];  
        if ( !mark[v] )  
        {  
            tarjan ( v );  
            low[u] = min ( low[u] , low[v] );  
        }  
        if ( mark[v] == 1 )  
            low[u] = min ( low[u] , dfn[v] );  
    }  
    if ( dfn[u] == low[u] )  
    {  
        int temp;  
        do  
        {  
            temp = s.top();  
            b[temp] = cnt;  
            sum[cnt]++;  
            mark[temp] = 2;  
            s.pop();  
        }while ( temp != u );  
        cnt++;  
    }  
}  

----------------------------------------强连通分量的应用-----------------------------------------------------------------

对于一个有向图,我们可以通过强连通分量得到一个DAG(有向无环图),这种有很优良的性质,能够进行拓扑排序,进行动态规划等等。一般在算法中作为预处理用到。



你可能感兴趣的:(C++,图论,强连通分量)