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 */