HDU 4635 Strong connected | tarjan算法

来源:互联网 发布:2016非农数据公布时间 编辑:程序博客网 时间:2024/05/16 17:34
#include<cstdio>#include<cstring>#include<iostream>#include<iomanip>#include<queue>#include<cmath>#include<stack>#include<map>#include<vector>#include<set>#include<algorithm>using namespace std;typedef long long LL;const int int_max = 0x07777777;const int int_min = 0x80000000;int smaller (int a, int b) { return (a > b ? b : a); }long long bigger (long long a, long long b) { return (a > b ? a : b); }const int maxn = 200005;vector<int> g[maxn];int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;int outs[maxn],ins[maxn],geshu[maxn];stack<int> S;void dfs (int u){    pre[u] = lowlink[u] = ++dfs_clock;    S.push(u);    for(int i = 0; i < g[u].size(); i++){        int v = g[u][i];        if(!pre[v]){            dfs(v);            lowlink[u] = smaller(lowlink[u], lowlink[v]);        }else if(!sccno[v]){            lowlink[u] = smaller(lowlink[u], pre[v]);        }    }    if(lowlink[u]==pre[u]){        scc_cnt++;        while (true) {            int x = S.top();            S.pop();            sccno[x] = scc_cnt;            if(x==u) break;        }    }}void find_scc (int n){    dfs_clock = scc_cnt = 0;    memset(sccno, 0, sizeof(sccno));    memset(pre, 0, sizeof(pre));    for(int i = 1; i <= n; i++){        if(!pre[i]) dfs(i);    }}long long N,M;int main(int argc, const char * argv[]){    int T;    scanf("%d", &T);    int casecount = 1;    while(T--){        scanf("%d %d", &N, &M);        for(int i = 0; i < maxn; i++) g[i].clear();        for(int i = 0; i < M; i++){            int x,y;            scanf("%d %d", &x, &y);            g[x].push_back(y);        }        find_scc(N);        if(scc_cnt==1) printf("Case %d: -1\n",casecount++);        else{            memset(outs, 0, sizeof(outs));            memset(ins, 0, sizeof(ins));            memset(geshu, 0, sizeof(geshu));            for(int i = 1; i <= N; i++){                for(int j = 0; j < g[i].size(); j++){                    if(sccno[i]!=sccno[g[i][j]]){                        outs[sccno[i]]++;                        ins[sccno[g[i][j]]]++;                    }                }                geshu[sccno[i]]++;            }            long long result = 0;            for(int i = 1; i <= scc_cnt; i++){                if(outs[i]==0 || ins[i]==0){                    result = bigger(result, N*(N-1)-M-(N-geshu[i])*geshu[i]);                }            }            printf("Case %d: %lld\n",casecount++,result);        }    }}
对一个有向图,找出所有的强连通分量之后,把每一个强连通分量看成一个点,这些点当中肯定存在一个入度或者出度为零的点(用反证法证明)。
0 0
原创粉丝点击