这个题的意思是一个有向图,你最多能加多少条边,它还不会是强连通图,加的边不能有重边。只需这个图变成两个强连通,而且是一个连通分量只能指向另一个连通分量,可以先缩点。
真心没想到
#include<iostream> using namespace std; const int N=100010; struct node { int to,next; }edge[N]; int head[N],dfn[N],low[N],belong[N],in[N],out[N],num[N]; int tot,index,top,color,n; int sta[N],instack[N]; __int64 ans; void add(int a,int b) { edge[tot].to=b; edge[tot].next=head[a]; head[a]=tot++; } int min(int a,int b) { if(a<b)return a; return b; } void tarjan(int u) { int i; dfn[u]=low[u]=++index; sta[top++]=u; instack[u]=1; for(i=head[u];i+1;i=edge[i].next) { int v=edge[i].to; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); }else if(instack[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { color++; int v; do { v=sta[--top]; instack[v]=0; belong[v]=color; num[color]++; }while(v!=u); } } void init() { for(int i=0;i<=n;i++) { instack[i]=0; head[i]=-1; dfn[i]=0; in[i]=0; num[i]=0; out[i]=0; } tot=top=index=color=ans=0; } __int64 max(__int64 a,__int64 b) { if(a>b)return a; return b; } int main() { int m,a,b,i,t,j,cas=0; scanf("%d",&t); while(cas<t) { scanf("%d%d",&n,&m); init(); for(i=0;i<m;i++) { scanf("%d%d",&a,&b); add(a,b); } for(i=1;i<=n;i++) if(!dfn[i]) tarjan(i); printf("Case %d: ",cas+1); if(color==1) { printf("%d ",-1); cas++; continue; } for(i=1;i<=n;i++) { for(j=head[i];j+1;j=edge[j].next) { int v=edge[j].to; if(belong[i]!=belong[v]) { in[belong[v]]++; out[belong[i]]++; } } } __int64 sum=(__int64)n*(n-1)-m; for(i=1;i<=color;i++) { if(in[i]==0||out[i]==0) { ans=max(ans,sum-(__int64)num[i]*(n-num[i])); } } printf("%I64d ",ans); cas++; } return 0; }