zoukankan      html  css  js  c++  java
  • hdu2767 强连通分量

    hdu2767 Proving Equivalences
    传送门
    题意
    给定一个(n(1leq nleq 20000))个顶点,(m(0leq mleq 50000))条边的有向图,至少添加几条边可以使得整个图变成强连通图?
    题解
    强连通分量缩点,判断每个点的出度或者入度是否为零,最终结果为出度为零的点的个数与入度为零的点的个数的最大值


    图连通时的连边方式,红色表示新加入的边

    图不连通时的连边方式,红色表示新加入的边

    ps:如果原图本身就是强连通图,需要特判结果为零

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<cstring>
    #include<string>
    #include<sstream>
    #include<cmath>
    #include<ctime>
    #include<climits>
    #include<algorithm>
    #define LL long long
    #define PII pair<int,int>
    #define PLL pair<LL,LL>
    #define pi acos(-1.0)
    #define eps 1e-6
    #define lowbit(x) x&(-x)
    using namespace std;
    
    const int maxn=20010,maxm=50010;
    int T,n,m;
    int head[maxn],nxt[maxm],to[maxm],cnt;
    int dfn[maxn],low[maxn],scc[maxn],stk[maxn],top,dfscnt,scccnt;
    int in[maxn],out[maxn];
    
    void add(int x,int y){
        to[cnt]=y;
        nxt[cnt]=head[x];
        head[x]=cnt++;
    }
    
    void tarjan(int u){
        dfn[u]=low[u]=++dfscnt;
        stk[++top]=u;
        for(int i=head[u];~i;i=nxt[i]){
            int v=to[i];
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(!scc[v]){
                low[u]=min(low[u],low[v]);
            }
        }
        if(dfn[u]==low[u]){
            scccnt++;
            while(1){
                int v=stk[top--];
                scc[v]=scccnt;
                if(v==u) break;
            }
        }
    }
    
    int main(){
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&m);
            memset(head,-1,sizeof(head));
            cnt=0;
            memset(dfn,0,sizeof(dfn));
            memset(scc,0,sizeof(scc));
            dfscnt=scccnt=top=0;
            for(int i=0;i<m;i++){
                int x,y;
                scanf("%d%d",&x,&y);
                add(x,y);
            }
            for(int i=1;i<=n;i++){
                if(!dfn[i]) tarjan(i);
            }
            memset(in,0,sizeof(in));
            memset(out,0,sizeof(out));
            for(int i=1;i<=n;i++){
                for(int j=head[i];~j;j=nxt[j]){
                    int v=to[j];
                    if(scc[i]!=scc[v]){
                        in[scc[v]]++;
                        out[scc[i]]++;
                    }
                }
            }
            int ans1=0,ans2=0;
            for(int i=1;i<=scccnt;i++){
                if(!in[i]) ans1++;
                if(!out[i]) ans2++;
            }
            if(scccnt==1) printf("0
    ");
            else printf("%d
    ",max(ans1,ans2));
        }
        return 0;
    }
    
  • 相关阅读:
    Hadoop 文件系统命令行基础
    Mac bash 远程连接阿里云服务器
    Master in Vocab -- Day Six
    Master in Vocab -- Day Five
    Master in Vocab -- Day Four
    Master in Vocab -- Day Three
    mybatis学习一
    mysql事务,视图,权限管理,索引,存储引擎(胖胖老师)
    SpringAOP
    Spring事务
  • 原文地址:https://www.cnblogs.com/fxq1304/p/13618074.html
Copyright © 2011-2022 走看看