给定一个有向图
求最多可以加多少条边 使加了边以后还是一个有向图而不是强联通图
由于不是一个强连通图,那么至少要有两个连通块。
也就是只有两个连通块时,加的边是最多的。
设有两个连通块
一个里有x个点,另一个里有个y个点
则第一个连通块中的路最多可以使x*(x-1)
第二个连通块中的路最多可以使y*(y-1)
两个连通块之间的路最多可以是(x*y)
那么一共可以连成x * (x-1)+y * (y-1)+x*y条边
又因为x+y=n
那么化简以后就是n*n-n-x*y
那么当x或y是0时 才有可能是答案
也就是找出入度或者出度是0的连通块
然后在减去一开始已经存在m条路
找出max(n*n+n-x*y-m)就是答案
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int maxn = 100005; const int maxm = 100005; int n, m; int top, tol, cnt; int stacksize; struct Node{ int u; int v; int next; }; Node node[maxm]; int dfn[maxn]; int low[maxn]; int vis[maxn]; int num[maxn]; int indi[maxn]; int oudi[maxn]; int head[maxn]; int stack[maxn]; int point[maxn]; void init() { tol = top = stacksize = cnt = 0; memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(num, 0, sizeof(num)); memset(indi, 0, sizeof(indi)); memset(oudi, 0, sizeof(oudi)); memset(node, 0, sizeof(node)); memset(head, -1, sizeof(head)); memset(vis, false, sizeof(vis)); memset(point, 0, sizeof(point)); memset(stack, 0, sizeof(stack)); } void addnode(int u, int v) { node[tol].u = u; node[tol].v = v; node[tol].next = head[u]; head[u] = tol++; } void dfs(int u) { int v; dfn[u] = low[u] = ++cnt; stack[stacksize++] = u; vis[u] = true; for(int i=head[u]; i!=-1; i=node[i].next) { v = node[i].v; if(!dfn[v]) { dfs(v); low[u] = min(low[u], low[v]); } else if(vis[v]) { low[u] = min(low[u], dfn[v]); } } if(low[u] == dfn[u]) { top++; do{ v = stack[--stacksize]; vis[v] = false; num[top]++; point[v] = top; } while(v != u); } } void tarjan() { for(int i=1; i<=n; i++) { if(!dfn[i]) { dfs(i); } } } int solve() { for(int u=1; u<=n; u++) { for(int i=head[u]; i+1; i=node[i].next) { int v = node[i].v; if(point[u] != point[v]) { oudi[point[u]]++; indi[point[v]]++; } } } int ans = 0; for(int i=1; i<=top; i++) { if(!oudi[i] || !indi[i]) { ans = max(ans, n*n-n-m-(n-num[i])*num[i]); } } return ans; } int main() { int T; scanf("%d", &T); int cas = 1; while(T--) { init(); scanf("%d%d", &n, &m); for(int i=0; i<m; i++) { int u, v; scanf("%d%d", &u, &v); addnode(u, v); } tarjan(); if(top == 1) { printf("Case %d: -1 ", cas++); } else { int ans = solve(); printf("Case %d: %d ", cas++, ans); } } }