Loading

HDU 4635:Strongly connected(强连通)

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("~~~\n");
 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\n", 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 */

 

posted @ 2016-10-04 11:31  Shadowdsp  阅读(336)  评论(0编辑  收藏  举报