HDOJ2767、3836解题报告【强连通分量】

题目地址:

  http://acm.hdu.edu.cn/showproblem.php?pid=2767

  http://acm.hdu.edu.cn/showproblem.php?pid=3836

题目概述:

  给出一张有向图,添加最少的边使这张图强连通,求最少需要添加的边数。

  3836跟2767的题面只有输入数据的方式差别,注意一下就可以了。

大致思路:

  先求出整个图的强连通分量然后缩点,在新图中统计出度为0和入度为0的点的个数,最大值即为答案。

  有些小细节需要注意,如果原图强连通应该输出0而不是1.

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <vector>
  6 #include <ctime>
  7 #include <map>
  8 #include <stack>
  9 #include <queue>
 10 #include <cstring>
 11 #include <algorithm>
 12 using namespace std;
 13 
 14 #define sacnf scanf
 15 #define scnaf scanf
 16 #define maxn  20010
 17 #define maxm 26
 18 #define inf 1061109567
 19 #define Eps 0.00001
 20 const double PI=acos(-1.0);
 21 #define mod 7
 22 #define MAXNUM 10000
 23 void Swap(int &a,int &b) {int t=a;a=b;b=t;}
 24 int Abs(int x) {return (x<0)?-x:x;}
 25 typedef long long ll;
 26 typedef unsigned int uint;
 27 
 28 int n,m;
 29 vector<int> G[maxn];
 30 stack<int> S;
 31 
 32 int pre[maxn],low[maxn],scc[maxn];
 33 int dfs_clock,scc_cnt;
 34 int in[maxn],out[maxn];
 35 
 36 void dfs(int u)
 37 {
 38     pre[u]=low[u]=++dfs_clock;
 39     int len=G[u].size();S.push(u);
 40     for(int i=0;i<len;i++)
 41     {
 42         int v=G[u][i];
 43         if(!pre[v])
 44         {
 45             dfs(v);
 46             low[u]=min(low[u],low[v]);
 47         }
 48         else if(!scc[v]) low[u]=min(low[u],pre[v]);
 49     }
 50     if(pre[u]==low[u])
 51     {
 52         scc_cnt++;
 53         for(;;)
 54         {
 55             int t=S.top();S.pop();
 56             scc[t]=scc_cnt;
 57             if(t==u) break;
 58         }
 59     }
 60 }
 61 
 62 void find_scc()
 63 {
 64     memset(pre,0,sizeof(pre));
 65     memset(low,0,sizeof(low));
 66     memset(scc,0,sizeof(scc));
 67     dfs_clock=0;scc_cnt=0;
 68     for(int i=1;i<=n;i++)
 69         if(!pre[i]) dfs(i);
 70 }
 71 
 72 int main()
 73 {
 74     //freopen("data.in","r",stdin);
 75     //freopen("data.out","w",stdout);
 76     //clock_t st=clock();
 77     int T;scanf("%d",&T);
 78     while(T--)
 79     {
 80         scanf("%d%d",&n,&m);
 81         int a,b;
 82         for(int i=1;i<=n;i++) G[i].clear();
 83         for(int i=1;i<=m;i++)
 84         {
 85             scanf("%d%d",&a,&b);
 86             G[a].push_back(b);
 87         }
 88         find_scc();
 89         for(int i=1;i<=scc_cnt;i++) in[i]=out[i]=0;
 90         for(int i=1;i<=n;i++)
 91         {
 92             int len=G[i].size();
 93             for(int k=0;k<len;k++)
 94             {
 95                 int j=G[i][k];
 96                 if(scc[i]==scc[j]) continue;
 97                 in[scc[j]]++;out[scc[i]]++;
 98             }
 99         }
100         int ans1=0,ans2=0;
101         for(int i=1;i<=scc_cnt;i++)
102         {
103             if(!in[i]) ans1++;
104             if(!out[i]) ans2++;
105         }
106         printf("%d\n",(scc_cnt==1)?0:max(ans1,ans2));
107     }
108     //clock_t ed=clock();
109     //printf("\n\nTime Used : %.5lf Ms.\n",(double)(ed-st)/CLOCKS_PER_SEC);
110     return 0;
111 }

 

posted @ 2017-03-24 10:26  CtrlKismet  阅读(134)  评论(0编辑  收藏  举报