题目链接:https://vjudge.net/problem/HDU-4635#author=0
转自:https://xiaoxiaoh.blog.csdn.net/article/details/104441555
题意:给一个有向无重边无自环的图,求最多可以添加多少边,让其仍然不连通,没有重边且没有自环。
思路:一个n个点的有向完全图的边数为n* (n-1),已经有了m条边,剩余n* (n-1)-m条边,由于最后的图不能是强连通,要减去包括点数目最少的强连通分量s的出边或入边才能保证添加边尽可能多的同时图不强连通,结果为n* (n-1)-m-minn* (n-minn)。同时要保证找到的s的入度或出度为0,否则无论怎么加边,s与合并后的连通分量是强连通的。当s入度为0,减去的是s的入边,反之减去的是出边。
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <cstring>
#include <iostream>
#include <cmath>
#include <set>
#include <fstream>
#include <list>
#include <stack>
#include <map>
using namespace std;
const int maxn=1e5+5;
vector <int> g[maxn];
vector <pair<int,int> >edge;
int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt,cntD[maxn];
int in[maxn],out[maxn];
stack<int> s;
void dfs(int u)
{
pre[u]=lowlink[u]=++dfs_clock;
s.push(u);
for(int i=0; i<g[u].size(); i++)
{
int v=g[u][i];
if(!pre[v])
{
dfs(v);
lowlink[u]=min(lowlink[u],lowlink[v]);
}
else if(!sccno[v])
{
lowlink[u]=min(lowlink[u],pre[v]);
}
}
if(lowlink[u]==pre[u])
{
scc_cnt++;
while(1)
{
int x=s.top();
s.pop();
sccno[x]=scc_cnt;
if(x==u)
break;
}
}
}
void find_scc(int n)
{
dfs_clock=scc_cnt=0;
memset(sccno,0,sizeof(sccno));
memset(pre,0,sizeof(pre));
for(int i=1; i<=n; i++)
{
if(!pre[i])
dfs(i);
}
}
int main()
{
int T,kase=1;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
edge.clear();
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(cntD,0,sizeof(cntD));
for(int i=0; i<=n; i++)
{
g[i].clear();
}
for(int i=0; i<m; i++)
{
int x,y;
scanf("%d%d",&x,&y);
g[x].push_back(y);
edge.push_back(make_pair(x,y));
}
find_scc(n);
printf("Case %d: ",kase++);
if(scc_cnt==1)
{
printf("-1\n");
continue;
}
for(int i=0; i<m; i++)
{
int u=edge[i].first,v=edge[i].second;
if(sccno[u]!=sccno[v])
{
in[sccno[v]]++;
out[sccno[u]]++;
}
}
for(int i=1;i<=n;i++)
{
cntD[sccno[i]]++;
}
int minn=1e9;
for(int i=1; i<=scc_cnt; i++)
{
if(!in[i]||!out[i])
{
minn=min(minn,cntD[i]);
}
}
long long ans=(long long ) n*(n-1);
ans-=m;
ans=ans-(long long )minn*(n-minn);
printf("%lld\n",ans);
}
return 0;
}