题目:给出一个有向图,要求添加最多的边数,使得图仍然不强连通.
思路:首先这个图在添加边之后肯定变成了两个强连通分量,现在就看怎么分.然后我们可以注意到,原图进行强连通分量分解之后必然存在一些分量的出度或入度为0,最小的分量肯定在这些分量之中.那么找出这个分量就可以得出的结果了.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
/* * @author: Cwind */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <functional> #include <set> #include <cmath> using namespace std; #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0) #define pb push_back #define PB pop_back #define bk back() #define fs first #define se second #define sq(x) (x)*(x) #define eps (1e-7) #define IINF (1<<29) #define LINF (1ll<<59) #define INF 1000000000 typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; typedef pair<ll,ll> P; inline void debug_case(){static int cas=1;printf("<---------------Case #:%d------------------>\n",cas);cas++; } const int maxn=1e5+300; int T; int n,m; vector<int> G[maxn]; int dfn[maxn]; int clo; int inscc[maxn],stk[maxn],low[maxn],top,sccid,cnt[maxn]; bool instk[maxn]; void tarjan(int v,int f){low[v]=dfn[v]=++clo;stk[top++]=v;instk[v]=1;for(int i=0;i<G[v].size();i++){int u=G[v][i];if(!dfn[u]){tarjan(u,v);low[v]=min(low[v],low[u]);}else if(instk[u]){low[v]=min(low[v],dfn[u]);}}if(low[v]==dfn[v]){sccid++;do{inscc[stk[--top]]=sccid;cnt[sccid]++;instk[stk[top]]=0;}while(stk[top]!=v);} } int d1[maxn],d2[maxn]; void init(){for(int i=0;i<=n;i++){G[i].clear();d2[i]=d1[i]=cnt[i]=dfn[i]=0;}sccid=top=clo=0; } int cas=0; int main(){freopen("/home/files/CppFiles/in","r",stdin);//freopen("defense.in","r",stdin);//freopen("defense.out","w",stdout);cin>>T;while(T--){// debug_case();scanf("%d%d",&n,&m);init();for(int i=0;i<m;i++){int a,b;scanf("%d%d",&a,&b);G[a].pb(b);}for(int i=1;i<=n;i++){if(!dfn[i]) tarjan(i,-1);}for(int i=1;i<=n;i++){for(int j=0;j<G[i].size();j++){int u=G[i][j];if(inscc[u]!=inscc[i]){d1[inscc[u]]++;d2[inscc[i]]++;}}}int minn=1e9;for(int i=1;i<=sccid;i++){if(d1[i]==0) minn=min(minn,cnt[i]);if(d2[i]==0) minn=min(minn,cnt[i]);}ll a=n-minn,b=minn;ll ans=(ll)n*(n-1)-(ll)a*b-(ll)m;if(sccid==1) ans=-1;printf("Case %d: %lld\n",++cas,ans);}return 0; }