HDU 4635 Strongly connected
题目大意:
给你N个顶点,M条边的有向图,问最多加入多少条边之后,这个图仍旧是一个简单图(简单图:无重边,无自环),
并且不是强联通的。如果原始的图就是强联通的话就输出 -1.
1.找出强联通块,计算每个连通块内的点数。将点数最少的那个连通块单独拿出来,其余的连通块合并成一个连通分量。 那么假设第一个连通块的 点数是 x 第二个连通块的点数是 y, 已经有的边数是 m 则
ans = x*(x-1) + y*(y-1) + x*y - m;(强联通块内边数最多是 n*(n-1) ),
这里最少点数的强联通分量要满足一个条件,就是出度或者入度为 0才行,不然是不满足的。
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <algorithm> #include <vector> usingnamespace std; #define INF 0x7ffffff #define maxn 100005 typedef longlong LL; #define Min(a,b) (a<b?a:b) int low[maxn], dfn[maxn], Time, m, n, belong[maxn]; int Stack[maxn], top, blocks, sum[maxn], InDegree[maxn], OutDegree[maxn]; bool InStack[maxn]; vector<vector<int> > G; void init() { memset(InDegree, 0, sizeof(InDegree)); memset(OutDegree, 0, sizeof(OutDegree)); memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(InStack, false, sizeof(InStack)); memset(belong, 0, sizeof(belong)); memset(sum, 0, sizeof(sum)); blocks = Time = top = 0; G.clear(); G.resize(n+2); } void Tarjan(int u) { low[u] = dfn[u] = ++Time; Stack[top++] = u; InStack[u] = true; int len = G[u].size(), v; for(int i=0; i<len; i++) { v = G[u][i]; if( !low[v] ) { Tarjan(v); low[u] = min(low[u], low[v]); } elseif( InStack[v] ) low[u] = min(low[u], dfn[v]); } if(low[u] == dfn[u]) { do { v = Stack[--top]; belong[v] = blocks; InStack[v] = false; sum[blocks] ++; }while(u != v); blocks ++; } } void solve() { for(int i=1; i<=n; i++) { if( !low[i] ) Tarjan(i); } for(int i=0; i<=n; i++) { int len = G[i].size(), v; for(int j=0; j<len; j++) { v = G[i][j]; int a = belong[i], b = belong[v]; if(a != b) { OutDegree[a] ++; InDegree[b] ++; } } } LL x = INF, y; for(int i=0; i<blocks; i++) { if( !OutDegree[i] || !InDegree[i]) x = Min(x, sum[i]); } y = n - x; LL ans = x*(x-1) + y*(y-1) + x*y - m; if(blocks == 1) printf("-1\n"); else printf("%lld\n", ans); } int main() { int T, cas = 1; scanf("%d", &T); while(T--) { scanf("%d %d",&n, &m); init(); for(int i=0; i<m; i++) { int a, b; scanf("%d %d", &a, &b); G[a].push_back(b); } printf("Case %d: ", cas ++); solve(); } return0; }