HDU4635 Strongly connected
给定一个有向图,问最多添加多少条边它不会变成强连通图
tarjan缩点+最多加边模板~
#include<cstdio> #include<algorithm> #include<vector> #include<stack> using namespace std; const int maxn=100014; typedef long long ll; vector<int> g[maxn]; int N,M,x,y; int low[maxn]; int dfn[maxn]; int cnt; int scc; int pos[maxn]; int in[maxn]; int out[maxn]; int num[maxn];//各强连通分量包含点的个数 stack<int> st; void init () { while (!st.empty()) st.pop(); fill(low,low+maxn,0); fill(dfn,dfn+maxn,0); fill(pos,pos+maxn,0); fill(in,in+maxn,0); fill(out,out+maxn,0); fill(num,num+maxn,0); scc=0; cnt=0; for (int i=0;i<maxn;i++) g[i].clear(); } void tarjan (int x) { low[x]=dfn[x]=++cnt; st.push(x); for (int i=0;i<g[x].size();i++) { if (!low[g[x][i]]) { tarjan(g[x][i]); low[x]=min(low[x],low[g[x][i]]); } else if (!pos[g[x][i]])low[x]=min(low[x],dfn[g[x][i]]); } if (low[x]==dfn[x]) { scc++; while (1) { int u=st.top(); st.pop(); low[u]=low[x]; pos[u]=scc; if (u==x) break; } } } void build () { for (int i=1;i<=N;i++) { num[pos[i]]++; for (int j=0;j<g[i].size();j++) { if (pos[i]!=pos[g[i][j]]) { out[pos[i]]++; in[pos[g[i][j]]]++; } } } } int main () { int T; scanf ("%d",&T); for (int k=1;k<=T;k++) { scanf ("%d %d",&N,&M); init (); for (int i=0;i<M;i++) { scanf ("%d %d",&x,&y); g[x].push_back(y); } for (int i=1;i<=N;i++) if (!low[i]) tarjan (i); build(); ll ans1=(ll)N*(N-1)-M; ll ans2=0; for (int i=1;i<=scc;i++) { if (in[i]==0||out[i]==0) ans2=max(ans2,ans1-(ll)num[i]*(N-num[i])); } if (scc==1) ans2=-1; printf ("Case %d: %d\n",k,ans2); } return 0; }