图论 —— 图的连通性 —— Kosaraju 算法

【概述】

Kosaraju 算法是最容易理解,最通用的求强连通分量的算法,其关键的部分是同时应用了原图 G 和反图 GT 。

【基本思想】

1.对原图 G 进行 DFS 搜索,计算出各顶点完成搜索的时间 f

2.计算图的反图 GT,对反图也进行 DFS 搜索,但此处搜索时顶点的访问次序不是按照顶点标号的大小,而是按照各顶点 f 值由大到小的顺序

3.反图 DFS 所得到的森林即对应连通区域。

原图

图论 —— 图的连通性 —— Kosaraju 算法_第1张图片

原图进行 DFS

图论 —— 图的连通性 —— Kosaraju 算法_第2张图片

反图

图论 —— 图的连通性 —— Kosaraju 算法_第3张图片

反图进行 DFS

图论 —— 图的连通性 —— Kosaraju 算法_第4张图片

上面提及原图 G 的反图 GT,其定义为 GT=(V,ET),ET={(u,v):(v,u)∈E}

也就是说 GT 是由 G 中的边反向所组成的,通常也称之为图 G 的转置。

值得一提的是,逆图 GT 和原图 G 有着完全相同的连通分支,也就说,如果顶点 s 和 t 在 G 中是互达的,当且仅当 s 和 t 在 GT 中也是互达的。

【伪代码】

step1:对原图 G 进行 DFS 遍历,记录每个节点的离开时间 num[i]

step2:选择具有最晚离开时间的顶点,对反图 GT 进行遍历,删除能够遍历到的顶点,这些顶点构成一个强连通分量

step3:如果还有顶点没有删除,继续 step2,否则算法结束

【实现】

int n,m;
vector g[N];
vector gt[N];
bool vis[N];//访问标志数组
int color[N];//存储强连通分量,color[i]表示顶点i属于第color[i]个强连通分量
int num[N];//结束时间标记,num[i]表示离开时间为i的顶点
int sig;//强连通分量个数
void dfs1(int x){//第一次深搜,求numb[1..n]的值
    vis[x]=true;
    for(int i=0;i=1;i--){
        if(vis[num[i]]==0){
            sig++;
            dfs2(num[i]);
        }
    }
}
int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        for(int i=1;i<=n;i++){
            g[i].clear();
            gt[i].clear();
        }
        for(int i=0;i

你可能感兴趣的:(#,图论——图的连通性)