zoukankan      html  css  js  c++  java
  • UVALive 4287 Proving Equivalence (强连通分量)

    把证明的关系看出一张图,最终就是要所有的点都在至少一个环中。环的判断和度数有关。

    用tarjan找强连通分量,在一个强连通分量点已经等价缩点以后形成一个DAG,计算入度为0的点数a,

    出度为0的b,取其中大的一个。特判强连通分量数为1的情况。

    看懂tarjan算法以后还是比较简单的

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2e4+5;
    const int maxm = 5e4+5;
    
    int head[maxn],nxt[maxm],to[maxm],ecnt;
    void addEdge(int u,int v)
    {
        nxt[ecnt] = head[u];
        to[ecnt] = v;
        head[u] = ecnt++;
    }
    
    void initGraph(int n)
    {
        memset(head,-1,sizeof(int)*(n+1)); ecnt = 0;
    }
    
    int sccno[maxn],pre[maxn],low[maxn],dfs_clock,scc_cnt;
    stack<int> stk;
    
    void tarjan(int u)
    {
        pre[u] = low[u] = ++dfs_clock;
        stk.push(u);
        for(int i = head[u]; ~i; i = nxt[i]){
            int v = to[i];
            if(!pre[v]){
                tarjan(v);
                low[u] = min(low[u],low[v]);
            }else if(!sccno[v]){
                low[u] = min(low[u],pre[v]);
            }
        }
        if(low[u] == pre[u]){
            scc_cnt++;
            while(stk.size()){
                int x = stk.top(); stk.pop();
                sccno[x] = scc_cnt;
                if(x == u) break;
            }
        }
    }
    
    void find_scc(int n)
    {
        memset(pre,0,sizeof(int)*(n+1));
        memset(sccno,0,sizeof(int)*(n+1));
        scc_cnt = dfs_clock = 0;
        for(int i = 0; i < n; i++){
            if(!pre[i]) tarjan(i);
        }
    }
    
    int ind[maxn],outd[maxn];
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T; scanf("%d",&T);
        while(T--){
            int n,m; scanf("%d%d",&n,&m);
            initGraph(n);
            for(int i = 0; i < m; i++){
                int u,v; scanf("%d%d",&u,&v);
                addEdge(u-1,v-1);
            }
            find_scc(n);
            if(scc_cnt == 1) {
                printf("0
    "); continue;
            }
            for(int i = 1; i <= scc_cnt; i++) ind[i] = outd[i] = 0;
            for(int u = 0; u < n; u++){
                for(int i = head[u]; ~i; i = nxt[i]){
                    int v = to[i];
                    if(sccno[u] != sccno[v]) outd[sccno[u]]++,ind[sccno[v]]++;
                }
            }
            int a = 0,b = 0;
            for(int i = 1; i <= scc_cnt; i++){
                if(!outd[i]) b++;
                if(!ind[i]) a++;
            }
            printf("%d
    ",max(a,b));
        }
        return 0;
    }
  • 相关阅读:
    Servlet的建立以及配置使用
    maven 安装 及其 创建
    错误总结
    使用分层实现业务处理
    JSP数据交互(三)
    JSP数据交互(二)
    JSP数据交互(一)
    动态网页开发基础
    记录mysql编码问题
    .net core 2.0 升级 2.1 访问mysql出现bug解决
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4776959.html
Copyright © 2011-2022 走看看