您当前的位置: 首页 >  ar
  • 0浏览

    0关注

    1477博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

图论 求有向图的所有强连通分量 kosaraju算法

软件工程小施同学 发布时间:2021-03-08 09:15:25 ,浏览量:0

一、问题

如何找到有向图(a)中的所有强连通分量,如图(b)

 

 二、kosaraju算法

Kosaraju的算法(又称为–Sharir Kosaraju算法)是一个线性时间(linear time)算法找到的有向图的强连通分量。

 

1. 原理

它利用了一个事实,逆图(与各边方向相同的图形反转, transpose graph)有相同的强连通分量的原始图。

 

2. 逆图

将各边的方向反转

 

3. 算法图示

上图是对图G,进行一遍DFS(深度优先搜索)的结果,

  • 1、2、4、6
  • 1、3、5

 

每个节点有两个时间戳,即节点的

  • 发现时间u.d(左边,即搜索发现的时间)
  • 完成时间u.f(右边,即搜索返回的时间)

 

我们将完成时间较大的,按大小(从小到大)加入堆栈

1)每次从栈顶取出元素

2)检查是否被访问过

3)若没被访问过,以该点为起点,对逆图进行深度优先遍历

4)否则返回第一步,直到栈空为止

 

[ATTENTION] : 对逆图搜索时,从一个节点开始能搜索到的最大区块就是该点所在的强连通分量。

  • 从节点1出发,能走到  2 ,3,4 , 所以{1 , 2 , 3 , 4 }是一个强连通分量
  • 从节点5出发,无路可走,所以{ 5 }是一个强连通分量
  • 从节点6出发,无路可走,所以{ 6 }是一个强连通分量

自此Kosaraju Algorithm完毕,这个算法只需要两遍DFS即可,是一个比较易懂的求强连通分量的算法。

 

4. 算法复杂度

邻接表:O(V+E)

邻接矩阵:O(V^2)

 该算法在实际操作中要比Tarjan算法要慢

 

5. 算法模板&注释代码
#include "cstdio"
#include "iostream"
#include "algorithm"

using namespace std ;

const int maxN = 10010 , maxM = 50010;

struct Kosaraju { int to , next ; } ;

Kosaraju E[ 2 ][ maxM ] ;
bool vis[ maxN ];
int head[ 2 ][ maxN ] , cnt[ 2 ] , ord[maxN] , size[maxN] ,color[ maxN ];

int tot , dfs_num  , col_num , N , M  ;

void Add_Edge( int x , int y , int _ ){//建图
         E[ _ ][ ++cnt[ _ ] ].to = y ;
         E[ _ ][ cnt[ _ ] ].next = head[ _ ][ x ] ;
         head[ _ ][ x ] = cnt[ _ ] ;
}

void DFS_1 ( int x , int _ ){
         dfs_num ++ ;//发现时间
         vis[ x ] = true ;
         for ( int i = head[ _ ][ x ] ; i ; i = E[ _ ][ i ].next ) {
                 int temp = E[ _ ][ i ].to;
                 if(vis[ temp ] == false) DFS_1 ( temp , _ ) ;
         }
         ord[(N            
关注
打赏
1665320866
查看更多评论
0.0482s