题意:问最多能添加多少条边使图仍为简单单向图(没有重边和环)且非强连通,若已经是强连通了,输出-1;
分析:tarjan求强连通缩点,具体参考http://blog.csdn.net/Jarily/article/details/13627397
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#define N 100005
#include<vector>
#include<stack>
using namespace std;
vector<int> v[N];
stack<int> s;
int n,cnt,index,dfn[N],low[N],id[N],in[N],out[N],instack[N],cnt_in,cnt_out,num[N];
void init(){
for(int i=1;i<=n;i++){
dfn[i]=0;
low[i]=0;
in[i]=0;
out[i]=0;
instack[i]=0;
cnt_in=0;
cnt_out=0;
v[i].clear();
}
memset(num,0,sizeof(num));
index=0;
cnt=0;
while(!s.empty())
s.pop();
}
void tarjan(int u){
instack[u]=1;
s.push(u);
dfn[u]=low[u]=++index;
int i,x;
for(i=v[u].size()-1;i>=0;i--){
x=v[u][i];
if(!dfn[x]){
tarjan(x);
low[u]=min(low[u],low[x]);
}else if(instack[x]){
low[u]=min(low[u],dfn[x]);
}
}
if(dfn[u]==low[u]){
do{
x=s.top();
s.pop();
instack[x]=0;
id[x]=cnt;
num[cnt]++;
}while(x!=u);
cnt++;
}
}
int main()
{
int t,ics=0,m,x,y,i,j;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m
ics++;
init();
for(i=0;i<m;i++){
scanf("%d%d",&x,&y);
v[x].push_back(y);
}
for(i=1;i<=n;i++){
if(!dfn[i])
tarjan(i);
}
printf("Case %d: ",ics);
if(cnt==1){
printf("-1\n");
continue;
}
for(i=1;i<=n;i++){
for(j=v[i].size()-1;j>=0;j--){
x=i;y=v[i][j];
if(id[x]!=id[y]){
in[id[y]]++;
out[id[x]]++;
}
}
}
int ans=0;
for(i=0;i<cnt;i++){
if(!in[i]||!out[i]){
x=num[i];
ans=max(ans,x*(n-x)+(n-x-1)*(n-x)+x*(x-1)-m);
}
}
printf("%d\n",ans);
}
return 0;
}