zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    那些ubuntu创建用户踩过的坑
    Build tools
    version control(以git为例)讲解
    URI和URL的区别
    HTTP解析过程心得
    函数式编程(functional programming)
    cb45a_c++_STL_算法_删除_(3)_unique(唯一的意思)删除连续性的重复的数据
    cb44a_c++_STL_算法_删除_(2)remove_copy_remove_copy_if
    cb43a_c++_STL_算法_删除_(1)remove_remove_if
    cb42a_c++_STL_算法_替换_replace
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/12313562.html
Copyright © 2011-2022 走看看