码迷,mamicode.com
首页 > 编程语言 > 详细

Kosaraju算法详解

时间:2017-04-11 15:56:19      阅读:436      评论:0      收藏:0      [点我收藏+]

标签:namespace   ++   退出   ace   遍历   构造   img   pac   string   

 
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算法详解

标签:namespace   ++   退出   ace   遍历   构造   img   pac   string   

原文地址:http://www.cnblogs.com/zwfymqz/p/6693881.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!