题目地址:
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 ",(scc_cnt==1)?0:max(ans1,ans2)); 107 } 108 //clock_t ed=clock(); 109 //printf(" Time Used : %.5lf Ms. ",(double)(ed-st)/CLOCKS_PER_SEC); 110 return 0; 111 }