分析:
完全图的边数为 n*(n-1)
若图不为强连通图,那么最多存在两个部
找出每个强连通的个数,当该连通图的入度或出度问为0时计算即可
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <stack>
#include <stack>
#include <vector>
using namespace std;
#define maxn 100050
vector<int>E[maxn];
stack<int>st;
int dfn[maxn];
int low[maxn];
int ins[maxn];
int nub[maxn];
int cnt ;
int time;
int belong[maxn];
int T;
int n , m;
int in[maxn];
int out[maxn];
void init()
{
time = cnt = 0;
memset(ins,0,sizeof(ins));
memset(belong,0,sizeof(belong));
memset(nub,0,sizeof(nub));
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
while(st.size())st.pop();
for(int i = 0 ; i < maxn ;++i)
E[i].clear();
}
void Tarjan(int u)
{
low[u] = dfn[u] = ++time;
st.push(u);
ins[u] = 1;
for(int i = 0 ; i < E[u].size() ; ++i)
{
int v = E[u][i];
if( !dfn[v] )
{
Tarjan(v);
low[u] = min( low[u],low[v] );
}
else if( ins[v] )
{
low[u] = min( low[u] , dfn[v] );
}
}
int tmp;
if( low[u] == dfn[u] )
{
cnt++;
do{
tmp = st.top();st.pop();
ins[tmp] = 0;
belong[tmp] = cnt;
nub[cnt]++;
}while( tmp != u );
}
}
void deal()
{
for(int i = 1 ; i <= n ; ++i)
{
if(!dfn[i])
{
Tarjan(i);
}
}
if( cnt == 1 )
{
printf("-1\n");
return ;
}
for(int u = 1; u <= n ; ++u)
{
for (int i = 0; i < E[u].size() ; ++i)
{
int v = E[u][i];
if (belong[u] != belong[v])
{
in[belong[v]] ++;
out[belong[u]] ++;
}
}
}
int result = 0;
for (int i = 1; i <= cnt; i++)
{
if (!in[i] || !out[i])
{
int t = nub[i];
int temp = t * (t - 1) + (n - t) * (n - t - 1) + t * (n - t) - m;
result = result > temp ? result : temp;
}
}
printf("%d\n", result);
}
int main()
{
cin >> T;
int cas = 0;
while ( T-- )
{
init();
cin >> n >> m ;
for(int i = 0 ; i < m ; ++i)
{
int a,b;
scanf("%d %d",&a,&b);
E[a].push_back(b);
}
printf("Case %d: ",++cas);
deal();
}
}