zoukankan      html  css  js  c++  java
  • HDOJ 2767 Proving Equivalences(强连通算法入门)

    题意:

    一个有向图,问至少添加几条边让整个图变成强连通图。

    思路:

    1. 基本上是模板题,首先对有向图进行缩点,即把所有强连通分量看成是一个点,Targan 算法 http://www.byvoid.com/blog/scc-tarjan/

    2. 统计出度和入度为 0 的点的个数,输出其中的最大的一个即可。

    #include <iostream>
    #include <vector>
    #include <stack>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 20010;
    
    vector<int> G[MAXN];
    stack<int> S;
    int dfn[MAXN], low[MAXN], sccno[MAXN], tclock, scccnt;
    int indeg[MAXN], outdeg[MAXN];
    
    void targan(int u) {
        dfn[u] = low[u] = ++tclock;
        S.push(u);
    
        for (int i = 0; i < G[u].size(); i++) {
            int v = G[u][i];
            if (!dfn[v]) {
                targan(v);
                low[u] = min(low[u], low[v]);
            } else if (!sccno[v]) {
                low[u] = min(low[u], dfn[v]);
            }
        }
    
        if (low[u] == dfn[u]) { 
            scccnt += 1;
            int v = -1;
            while (v != u) {
                v = S.top(); 
                S.pop();
                sccno[v] = scccnt;
            }
        }
    }
    
    void findscc(int n) {
        tclock = scccnt = 0;
    
        memset(sccno, 0, sizeof(int)*(n+1));
        memset(dfn, 0, sizeof(int)*(n+1));
        memset(low, 0, sizeof(int)*(n+1));
    
        for (int i = 1; i <= n; i++) 
            if (!dfn[i])  targan(i);
    }
    
    int workout(int n) {
        if (scccnt == 1) 
            return 0;
    
        memset(indeg, 0, sizeof(int)*(n+1));
        memset(outdeg, 0, sizeof(int)*(n+1));
    
        for (int u = 1; u <= n; u++) {
            for (int i = 0; i < G[u].size(); i++) {
                int v = G[u][i];
                if (sccno[u] != sccno[v]) {
                    indeg[sccno[v]] += 1;
                    outdeg[sccno[u]] += 1;
                }
            }
        }
    
        int c1 = 0, c2 = 0;
        for (int i = 1; i <= scccnt; i++) {
            if (indeg[i] == 0) c1 += 1;
            if (outdeg[i] == 0) c2 += 1;
        }
    
        return max(c1, c2);
    }
    
    int main() {
        int cases;
        scanf("%d", &cases);
        while (cases--) {
            int n, m;
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; i++)
                G[i].clear();
            for (int i = 0; i < m; i++) {
                int u, v;
                scanf("%d%d", &u, &v);
                G[u].push_back(v);
            }
            findscc(n);
            printf("%d\n", workout(n));
        }
        return 0;
    }
  • 相关阅读:
    理财课堂笔记第9天
    李筱懿的《先谋生,再谋爱》读后感
    bat想要写一个卸载软件的脚本,最后宣布失败[未完待续...]
    理财课堂日记第7天
    理财课堂日记第6天
    理财课堂日记第5天
    bat脚本登陆ftp服务器
    理财课堂笔记第4天
    理财课堂日记第3天
    理财课堂日记第2天
  • 原文地址:https://www.cnblogs.com/kedebug/p/3010299.html
Copyright © 2011-2022 走看看