NYOJ 120校园网络(有向图的强连通分量)(Kosaraju算法)

找出各个顶点所属的连通分量,将连通分量的点看作一个点,求这些顶点入度为0的个数和出度0的个数,取最大的即可。

 1 #include<iostream>
 2 #include<vector>
 3 #include<cstdio>
 4 #include<cstring>
 5 #define maxn 102
 6 using namespace std;
 7 vector<int> G[maxn],G2[maxn];
 8 vector<int> s;//
 9 int vis[maxn],
10     sccno[maxn],                            //标记顶点所属的连通分量
11     scc_cnt;                                 //记录有几个强连通分量
12 void dfs1(int u)
13 {
14     if(vis[u]) return ;                     //顶点遍历过则返回
15     vis[u] = 1;
16     for(int i=0; i<G[u].size(); i++)dfs1(G[u][i]);
17     s.push_back(u);                         //将一颗树上的顶点入栈
18 }
19 void dfs2(int u)
20 {
21     if(sccno[u])return ;
22     sccno[u] = scc_cnt;                     //标记顶点所属的连通分量
23     for(int i=0; i<G2[u].size(); i++)dfs2(G2[u][i]);
24 }
25 void find_scc(int n)
26 {
27     int i;
28     scc_cnt = 0;
29     s.clear();
30     memset(sccno,0,sizeof(sccno));
31     memset(vis,0,sizeof(vis));
32     for(i=0; i<n; i++)dfs1(i);              //对所有顶点遍历,入栈
33     for(i=n-1; i>=0; i--)if( !sccno[s[i]] ){//找强连通分量,找过了则不用找了
34         scc_cnt++;                          //记录找到连通分量的个数
35         dfs2(s[i]);
36     }
37 }
38 int main()
39 {
40     //freopen("in.txt","r",stdin);
41     int i,j,T,n,u,ver;
42     int in0[maxn],out0[maxn];
43     cin>>T;
44     while(T--)
45     {
46         cin>>n;
47         for(i=1; i<=n; i++)
48         for(j=1; j<=n; j++){
49             cin>>ver;
50             if(ver==0)break;
51             G[i-1].push_back(ver-1); //原图
52             G2[ver-1].push_back(i-1);//逆向图
53         }
54         find_scc(n);                 //求连通分量
55         for(i=1; i<=scc_cnt; i++)in0[i] = out0[i] = 1;//同一个连通分量所有点看成一个点
56         for(u=0; u<n; u++)
57         for(i=0; i<G[u].size(); i++){
58             int v = G[u][i];
59             if(sccno[i] != sccno[v]) in0[sccno[v]] = out0[sccno[u]] = 0;
60         }
61         int a = 0,b = 0;            //分别统计入度和出度为0的顶点个数
62         for(i=1; i<=scc_cnt; i++){
63             if(in0[i])a++;
64             if(out0[i])b++;
65         }
66         int ans = max(a,b);         //取最大的输出
67         if(scc_cnt == 1) ans = 0;   //只有一个连通分量,说明是强连通图,加0条边
68         cout<<ans<<endl;
69         for(i=0; i<=n; i++){G[i].clear();G2[i].clear();}//清空
70     }
71     return 0;
72 }
View Code

 

posted @ 2013-07-30 11:45  SStep  阅读(228)  评论(0编辑  收藏  举报