Kosaraju算法详解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kosaraju算法详解相关的知识,希望对你有一定的参考价值。

 
Kosaraju算法可以求出有向图中的强连通分量个数,并且对分属于不同强连通分量的点进行标记。它的算法描述较为简单:
(1) 第一次对图G进行DFS遍历,并在遍历过程中,记录每一个点的退出顺序。以下图为例:
 技术分享技术分享
    如果以1为起点遍历,访问结点的顺序如下:
 

 技术分享

结点第二次被访问即为退出之时,那么我们可以得到结点的退出顺序:
 技术分享
(2)倒转每一条边的方向,构造出一个反图G。然后按照退出顺序的逆序对反图进行第二次DFS遍历。我们按14235的逆序第二次DFS遍历:
 技术分享技术分享

 

访问过程如下:
 技术分享
每次遍历得到的那些点即属于同一个强连通分量。14属于同一个强连通分量,235属于另一个强连通分量。

 代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 int map[101][101];
 6 int nmap[101][101];
 7 int pass[101];
 8 int vis[101];
 9 int now=1;
10 int n,m;
11 int num=0;
12 void dfs(int p)
13 {
14     vis[p]=1;
15     for(int i=1;i<=n;i++)
16     {
17         if(vis[i]==0&&map[p][i]==1)
18         {
19             dfs(i);
20         
21         }
22     }
23     pass[now]=p;
24     now++;
25 }
26 void ndfs(int p)
27 {
28     vis[p]=0;
29     for(int i=1;i<=n;i++)
30     {
31         if(vis[i]==1&&nmap[p][i]==1)
32         ndfs(i);
33     }
34 }
35 int main()
36 {
37     
38     scanf("%d%d",&n,&m);
39     for(int i=1;i<=m;i++)
40     {
41         int x,y;
42         scanf("%d%d",&x,&y);
43         map[x][y]=1;
44         nmap[y][x]=1;
45     }
46     for(int i=1;i<=n;i++)
47     {
48         if(vis[i]==0)
49         dfs(i);
50     }
51     pass[now]=1;
52     for(int i=n;i>=1;i--)
53     {
54         if(vis[pass[i]]==1)
55         {
56             ndfs(pass[i]);
57             num++;
58         }
59     }
60     cout<<num;
61     return 0;
62 }

 

以上是关于Kosaraju算法详解的主要内容,如果未能解决你的问题,请参考以下文章

Kosaraju算法——强连通分量

Kosaraju 算法

Kosaraju

求有向图的强连通分量个数 之 Kosaraju算法

寻找强连通分量 - Kosaraju 算法

Algorithms IV求解强连通分量 Kosaraju算法