hdu 4635 Strongly connected
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4635
大意:给出一个简单有向图,问最多可以向图中添加几条边,并且保证图不是强连通
解法:图的最后形式肯定是两部分X和Y,且两部分之间要么只有X到Y的边,要么只有Y到X的边,并且X和Y都是完全图,此时有边数为
ans = x*(x-1)+y*(y-1)+x*y,因为x+y = n,化简得:ans = n*n-n-x*y,当x尽可能小的时候,ans才会尽可能的大,所以
首先求强连通分量缩点,然后找到出度或入度为0(一定存在)中点数最少的强连通分量作为X,最后的答案还需要减去原来就存在的边
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 using namespace std; 6 7 const int Max = 200001; 8 9 int stop, visitnum, cnt; 10 int dfn[Max], low[Max], stack[Max], belong[Max], num[Max]; 11 int n, m, dego[Max], degi[Max]; 12 bool use[Max]; 13 vector < vector <int> > a(Max); 14 15 void tarjan(int i) 16 { 17 int j; 18 dfn[i] = low[i] = ++visitnum; 19 use[i] = 1; 20 stack[++stop] = i; 21 for (int k=0; k<a[i].size(); k++) 22 { 23 j = a[i][k]; 24 if (!dfn[j]) { 25 tarjan(j); 26 low[i] = min(low[i], low[j]); 27 }else if (use[j]) low[i] = min(low[i], dfn[j]); 28 } 29 if (dfn[i] == low[i]) 30 { 31 cnt ++; 32 do { 33 j = stack[stop--]; 34 use[j] = 0; 35 belong[j] = cnt; 36 num[cnt] ++; 37 } while (j != i); 38 } 39 } 40 41 long long calc() 42 { 43 if (cnt == 1) return -1; 44 for (int i=1; i<=n; i++) 45 for (int j=0; j<a[i].size(); j++) 46 if (belong[i] != belong[a[i][j]]) { 47 dego[belong[i]] ++; 48 degi[belong[a[i][j]]] ++; 49 } 50 int ans = Max; 51 for (int i=1; i<=cnt; i++) 52 if (!dego[i] || !degi[i]) ans = min(ans, num[i]); 53 long long p = n; 54 return p*p-p-ans*(p-ans)-m; 55 } 56 57 void solve() 58 { 59 cnt = stop = visitnum = 0; 60 memset(dfn, 0, sizeof(dfn)); 61 memset(use, 0, sizeof(use)); 62 memset(num, 0, sizeof(num)); 63 memset(dego, 0, sizeof(dego)); 64 memset(degi, 0, sizeof(degi)); 65 for (int i=1; i<=n; i++) 66 if (!dfn[i]) tarjan(i); 67 } 68 69 int main() 70 { 71 int T; scanf("%d", &T); 72 for (int t=1; t<=T; t++) 73 { 74 for (int i=0; i<Max; i++) a[i].clear(); 75 scanf("%d%d", &n, &m); 76 for (int i=0; i<m; i++) 77 { 78 int x, y; scanf("%d%d", &x, &y); 79 a[x].push_back(y); 80 } 81 solve(); 82 cout << "Case " << t << ": " << calc() << endl; 83 } 84 return 0; 85 }