zoukankan      html  css  js  c++  java
  • 图的连通性问题之强连通分量初步

    什么是强连通分量

    有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量。

    强连通分量的个数

    Kosaraju算法

    Kosaraju算法可以求出有向图中的强连通分量个数,并且对分属于不同强连通分量的点进行标记。
    算法描述:
    (1) 第一次对图G进行DFS遍历,并在遍历过程中,记录每一个点的退出顺序。以下图为例:
    这里写图片描述

    如果以1为起点遍历,访问结点的顺序如下:
    这里写图片描述

    结点第二次被访问即为退出之时,那么我们可以得到结点的退出顺序:
    这里写图片描述

    (2)倒转每一条边的方向,构造出一个反图G’。然后按照退出顺序的逆序对反图进行第二次DFS遍历。我们按1、4、2、3、5的逆序第二次DFS遍历:
    这里写图片描述

    访问过程如下:
    这里写图片描述

    每次遍历得到的那些点即属于同一个强连通分量。1、4属于同一个强连通分量,2、3、5属于另一个强连通分量。

    伪代码:

    #include<iostream>
    const int maxn=1000;
    bool g[maxn][maxn];
    int n,scc,dfn,topo[maxn];
    bool flag[maxn]
    void dfs(int v)
    {
        if(flag[v]) return;
        flag[v]=1;
        for(int i=0;i<n;i++)
        if(g[v][i]&&!flag[i])
        dfs(i);
        topo[dfn++]=v;
    }
    void ndfs(int v)
    {
        if(flag[v]) return;
        flag[v]=scc;
        for(int i=0;i<n;i++ )
        if(g[i][v]&&!flag[i])
        ndfs(i);
    }
    void kosaraju()
    {
        for(int i=0;i<n;i++)
        flag[i]=false;
        for(int i=0;i<n;i++)
        if(!flag[i])
        dfs(i);
        for(int i=0;i<n;i++)
        flag[i]=false;
        for(int i=dfn-1;i>=0;i--)
        if(!flag[topo[i]])
        {
            scc++;
            ndfs(topo[i]);
        }
    }
  • 相关阅读:
    树的直径 poj 2631
    hdu 3954 Level up(线段树)
    [Java Web]Struts2解决中文乱码问题
    怎样为virtualbox添加新的分辨率
    本人的cocos2d-x之路
    php 中利用json_encode和json_decode传递包括特殊字符的数据
    【设计模式】—— 创建者模式Builder
    【设计模式】——工厂方法FactoryMethod
    【Apache开源软件基金会项目】
    【设计模式】——抽象工厂Abstract Factory
  • 原文地址:https://www.cnblogs.com/cax1165/p/6071016.html
Copyright © 2011-2022 走看看