http://acm.hdu.edu.cn/showproblem.php?pid=4635
题意:给出n个点和m条边,问最多能添加几条边使得图不是一个强连通图。如果一开始强连通就-1.思路:把图分成x个强连通分量之后,每个强连通分量最大的边数是n*(n-1),然后考虑和其他强连通分量相连的情况:即把分量a的所有点都连向分量b的所有点,而b不连a,这样就可以让图不是强连通的。可以把整个图分成两个强连通分量a和b分别有i和j个点,其中i+j=n,那么答案就是n*(n-1)-m-i*j。所以求出最小的i*j就可以找到答案了。
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <string> 6 #include <cmath> 7 #include <queue> 8 #include <vector> 9 #include <stack> 10 using namespace std; 11 #define N 100010 12 struct node 13 { 14 int v, next, u; 15 }edge[N]; 16 17 int n, tot, cnt, num, head[N], dfn[N], low[N], belong[N], in[N], out[N], deg[N], tol[N], e[N]; 18 bool vis[N]; 19 stack<int> sta; 20 21 void init() 22 { 23 tot = 0; 24 num = 0; 25 cnt = 0; 26 while(!sta.empty()) sta.pop(); 27 memset(head, -1, sizeof(head)); 28 memset(vis, false, sizeof(vis)); 29 memset(low, 0, sizeof(low)); 30 memset(dfn, 0, sizeof(dfn)); 31 memset(belong, 0, sizeof(belong)); 32 memset(in, 0, sizeof(in)); 33 memset(out, 0, sizeof(out)); 34 memset(deg, 0, sizeof(deg)); 35 memset(tol, 0, sizeof(tol)); 36 memset(e, 0, sizeof(e)); 37 } 38 39 void add(int u, int v) 40 { 41 edge[tot].u = u; edge[tot].v = v; edge[tot].next = head[u]; head[u] = tot++; 42 } 43 44 void tarjan(int u) 45 { 46 vis[u] = 1; sta.push(u); 47 dfn[u] = low[u] = ++cnt; 48 for(int i = head[u]; ~i; i = edge[i].next) { 49 int v = edge[i].v; 50 if(!dfn[v]) { 51 tarjan(v); 52 if(low[v] < low[u]) low[u] = low[v]; 53 } else if(vis[v]) { 54 if(dfn[v] < low[u]) low[u] = dfn[v]; 55 } 56 } 57 if(low[u] == dfn[u]) { 58 ++num; 59 int top = -1; 60 while(top != u) { 61 top = sta.top(); sta.pop(); 62 vis[top] = 0; 63 belong[top] = num; 64 } 65 } 66 } 67 68 bool cmp(const int &a, const int &b) 69 { 70 if(out[a] != 0) return false; 71 if(out[b] != 0) return true; 72 return tol[a] < tol[b]; 73 } 74 75 int main() 76 { 77 int t, cas = 1; 78 scanf("%d", &t); 79 while(t--) { 80 int n, m; 81 scanf("%d%d", &n, &m); 82 init(); 83 for(int i = 0; i < m; i++) { 84 int u, v; 85 scanf("%d%d", &u, &v); 86 add(u, v); 87 deg[u]++; deg[v]++; 88 } 89 for(int i = 1; i <= n; i++) { 90 if(!dfn[i]) tarjan(i); 91 } 92 printf("Case %d: ", cas++); 93 if(num == 1) { 94 puts("-1"); continue; 95 } 96 // printf("~~~ "); 97 for(int u = 1; u <= n; u++) { 98 for(int i = head[u]; ~i; i = edge[i].next) { 99 int v = edge[i].v; 100 if(belong[u] != belong[v]) { 101 in[belong[v]]++; 102 out[belong[u]]++; 103 } 104 } 105 } 106 long long sum = (long long)n * (n - 1) - m; 107 for(int i = 1; i <= n; i++) { 108 int tmp = belong[i]; 109 tol[tmp]++; 110 } 111 long long ans = 0; 112 for(int i = 1; i <= num; i++) { 113 if(!in[i] || !out[i]) { 114 ans = max(ans, sum - (long long)(n - tol[i]) * tol[i]); 115 } 116 } 117 printf("%I64d ", ans); 118 } 119 return 0; 120 } 121 122 /* 123 1 124 6 7 125 1 2 126 2 3 127 3 1 128 4 5 129 5 6 130 6 4 131 6 1 132 */