------------------------------------------概念部分----------------------------------------------------------------
强连通是在有向图当中提出的概念,代表点点之间都可以互相达到
下面说几个具体的概念:
顶点强连通:在有向图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(有向无环图),这种有很优良的性质,能够进行拓扑排序,进行动态规划等等。一般在算法中作为预处理用到。