SCC缩点模板

struct SCC {
    int top = 0, cntscc = 0, dfncnt = 0, n;
    vector<int> dfn, low, stk, instk;
    vector<int> sccnum, sccid;
    vector<vector<int>> g, scc;

    SCC(int n_): n(n_) {
        //缩点
        dfn.assign(n + 1, 0);
        low.assign(n + 1, 0);
        stk.assign(n + 1, 0);
        sccnum.assign(n + 1, 0);
        sccid.assign(n + 1, 0);
        instk.assign(n + 1, 0);
        g.resize(n + 1);
        scc.resize(n + 1);
    }

    void add(int u, int v) {
        g[u].push_back(v);
    }

    //缩点
    void tarjan(int u) {
        dfn[u] = low[u] = ++dfncnt;
        stk[++top] = u;
        instk[u] = 1;

        i128 s = 0;
        for (auto v : g[u]) {
            if (!dfn[v]) {
                tarjan(v);
                low[u] = min(low[u], low[v]);
            } else if (instk[v]) {
                low[u] = min(low[u], dfn[v]);
            }
        }

        if (dfn[u] == low[u]) {
            cntscc ++;
            int v;
            do {
                v = stk[top --], instk[v] = 0;
                sccid[v] = cntscc;
                scc[cntscc].push_back(v);
                sccnum[cntscc] ++;
            } while (u != v);
        }
    }

    void work() {
        for (int i = 1; i <= n; i ++) {
            if (!dfn[i]) {
                dfncnt = 0;
                tarjan(i);
            }
        }
    }
};
posted @ 2024-07-18 20:39  Ke_scholar  阅读(12)  评论(1编辑  收藏  举报