hdu 3836 tarjain 求强连通分量个数

  1 //  给你一个有向图,问你最少加几条边能使得该图强连通
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <string>
  6 #include <utility>
  7 #include <algorithm>
  8 #include <vector>
  9 #include <queue>
 10 #include <stack>
 11 using namespace std;
 12 #define max(x,y) x>=y?x:y
 13 #define lowbit(x) x&(-x)
 14 typedef  long long ll;
 15 const int  N=20010;
 16 int n,m;
 17 int head[N],low[N],num[N];
 18 int  in[N],out[N],be[N];
 19 int  ans,cnt,ans1,ans2;
 20 int  index;
 21 bool vis[N];
 22 struct Edge
 23 {
 24     int from,to,nex;
 25 }e[N*6];
 26 stack<int>s;
 27 void init()
 28 {
 29     memset(head,-1,sizeof(head));
 30     memset(num,-1,sizeof(num));
 31     memset(vis,0,sizeof(vis));
 32     memset(low,0,sizeof(low));
 33     memset(in,0,sizeof(in));
 34     memset(out,0,sizeof(out));
 35     cnt=index=0;    
 36 }
 37 void add(int u,int v)
 38 {
 39     e[cnt].from=u;
 40     e[cnt].to=v;
 41     e[cnt].nex=head[u];
 42     head[u]=cnt++;
 43 }
 44 void tarjan(int u)
 45 {
 46     low[u]=num[u]=++index;
 47     vis[u]=1;
 48     s.push(u);
 49     for (int i=head[u];i!=-1;i=e[i].nex)
 50     {
 51         int v=e[i].to;
 52         if(num[v]==-1)
 53         {
 54             tarjan(v);
 55             low[u]=min(low[u],low[v]);
 56         }
 57         else if(vis[v])
 58         {
 59             low[u]=min(low[u],num[v]);
 60         }
 61     }
 62     if(num[u]==low[u])
 63     {
 64         int x;
 65         ans++;
 66         do{
 67             x=s.top();
 68             s.pop();
 69             vis[x]=0;
 70             be[x]=ans;
 71         }while(x!=u);
 72     }
 73 }
 74 int main()
 75 {
 76     while(~scanf("%d %d",&n,&m))
 77     {
 78         init();
 79         ans=0;
 80         int a,b;
 81         for (int i=0;i<m;i++)
 82         {
 83             scanf("%d %d",&a,&b);
 84             add(a,b);
 85             
 86         }
 87         for (int i=1;i<=n;i++)
 88         {
 89             if(num[i]==-1)
 90             {
 91                 tarjan(i);
 92             }
 93         }
 94         for (int i=0;i<cnt;i++)
 95         {
 96             int a=e[i].from;
 97             int b=e[i].to;
 98             if(be[a]!=be[b])
 99             {
100                 in[be[b]]++;
101                 out[be[a]]++;
102             }
103         }
104         ans1=ans2=0;
105         for (int i=1;i<=ans;i++)//ans 从1开始。ans为原图强联通分量的个数、
106         {
107             if(!in[i])
108             {
109                 ans1++;
110             }
111             if(!out[i])
112             {
113                 ans2++;
114             }
115         }
116         printf("%d\n",ans==1?0:max(ans1,ans2));    
117     }
118     return 0;
119 }
120 
121 /*
122 
123 3 2
124 1 2
125 2 3
126 
127 有3个联通快
128 
129 */

 

posted on 2018-07-15 16:56  cltt  阅读(139)  评论(0编辑  收藏  举报

导航