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
",k,ans2);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zhanglichen/p/12313562.html