给定一个有向图
求最多可以加多少条边 使加了边以后还是一个有向图而不是强联通图
由于不是一个强连通图,那么至少要有两个连通块。
也就是只有两个连通块时,加的边是最多的。
设有两个连通块
一个里有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\n", cas++);
} else {
int ans = solve();
printf("Case %d: %d\n", cas++, ans);
}
}
}