poj 1236(强连通分量)

题目大意:   给定一个n (n<=100)个点的有向图,

问:Q1、最少需要选择多少个点,使得从这些点出发能遍历完整个图; 

  Q2、最少需要添加多少条有向边,使得整个图成为强连通图; 

  分析: 

    求出强连通分量后进行缩点,得到每个强连通分量的入度in[],出度out[]; 

  Q1: 入度为0的强连通分量个数;   Q2: max( 入度为0的强连通分量个数 , 出度为0的强连通分量个数  );

  注意的地方:假如原图就是一个强连通图。则显然Q2是0.

kosaraju:

View Code
  1 // File Name: 1236.cpp

  2 // Author: Missa

  3 // Created Time: 2013/2/6 星期三 19:44:12

  4 

  5 #include<iostream>

  6 #include<cstdio>

  7 #include<cstring>

  8 #include<algorithm>

  9 #include<cmath>

 10 #include<queue>

 11 #include<stack>

 12 #include<string>

 13 #include<vector>

 14 #include<cstdlib>

 15 #include<map>

 16 using namespace std;

 17 

 18 const int maxn = 1e2+5;

 19 int n;

 20 vector<int>adj[maxn];

 21 vector<int>radj[maxn];

 22 vector<int>ord;

 23 bool vis[maxn];

 24 int ma[maxn];

 25 int cnt;

 26 void init()

 27 {

 28     for(int i=0;i<maxn;i++)

 29     {

 30         adj[i].clear();

 31         radj[i].clear();

 32     }

 33     ord.clear();

 34     cnt=0;

 35 }

 36 void dfs1(int v)

 37 {

 38     vis[v]=1;

 39     for(int i=0;i<adj[v].size();i++)

 40         if(!vis[adj[v][i]])

 41             dfs1(adj[v][i]);

 42     ord.push_back(v);

 43 }

 44 void dfs2(int v)

 45 {

 46     vis[v]=1;

 47     ma[v]=cnt;

 48     for(int i=0;i<radj[v].size();i++)

 49         if(!vis[radj[v][i]])

 50             dfs2(radj[v][i]);

 51 }

 52 void kosaraju()

 53 {

 54     memset(vis,0,sizeof(vis));

 55     ord.clear();

 56     for(int i=1;i<=n;i++)

 57         if(!vis[i])

 58             dfs1(i);

 59     memset(vis,0,sizeof(vis));

 60     cnt=0;

 61     for(int i=ord.size()-1;i>=0;i--)

 62     {

 63         if(!vis[ord[i]])

 64         {

 65             cnt++;

 66             dfs2(ord[i]);

 67         }

 68     }

 69 }

 70 void read()

 71 {

 72     for(int i=1;i<=n;i++)

 73     {

 74         int x;

 75         while(scanf("%d",&x))

 76         {

 77             if(x==0) break;

 78             adj[i].push_back(x);

 79             radj[x].push_back(i);

 80         }

 81     }

 82 }

 83 void solve()

 84 {

 85     int ans1=0,ans2=0;

 86     int in[maxn],out[maxn];//入度,出度

 87     memset(in,0,sizeof(in));

 88     memset(out,0,sizeof(out));

 89     for(int i=1;i<=n;i++)

 90     {

 91         for(int j=0;j<adj[i].size();j++)

 92         {

 93             int tt=adj[i][j];

 94             if(ma[i]==ma[tt]) continue;

 95             out[ma[i]]++;

 96             in[ma[tt]]++;

 97         }

 98     }

 99     for(int i=1;i<=cnt;i++)

100     {

101         if(in[i]==0) ans1++;

102         if(out[i]==0) ans2++;

103     }

104     printf("%d\n",ans1);

105     if(cnt==1)//原图是一个强连通分量

106         printf("0\n");

107     else

108         printf("%d\n",max(ans1,ans2));

109 }

110 int main()

111 {

112     while(~scanf("%d",&n))

113     {

114         init();

115         read();

116         kosaraju();

117         solve();

118     }

119     return 0;

120 }

 

你可能感兴趣的:(poj)