Alfred's CP Library

This documentation is automatically generated by online-judge-tools/verification-helper

View on GitHub

:warning: src/watashi/bcc.hpp

Code

#include <algorithm>
#include <stack>
#include <utility>
#include <vector>

using namespace std;

// TODO: cannot handle duplicate edges
struct Tarjan {
    int n;
    vector<vector<int>> e;

    vector<int> cut;
    vector<pair<int, int>> bridge;
    vector<vector<pair<int, int>>> bcc;

    void init(int n) {
        this->n = n;
        e.clear();
        e.resize(n);
        dfn.resize(n);
        low.resize(n);
    }

    void add(int a, int b) {
        // assert(find(e[a].begin(), e[a].end(), b) == e[a].end());
        e[a].push_back(b);
        e[b].push_back(a);
    }

    vector<int> dfn, low;
    int timestamp;
    stack<pair<int, int>> s;

    void dfs(int v, int p) {
        int part = p == -1 ? 0 : 1;
        dfn[v] = low[v] = timestamp++;
        for (vector<int>::const_iterator w = e[v].begin(); w != e[v].end(); ++w) {
            pair<int, int> f = make_pair(min(v, *w), max(v, *w));
            if (dfn[*w] == -1) {
                s.push(f);
                dfs(*w, v);
                low[v] = min(low[v], low[*w]);
                if (dfn[v] <= low[*w]) {
                    // articulation point
                    if (++part == 2) {
                        cut.push_back(v);
                    }
                    // articulation edge
                    if (dfn[v] < low[*w]) {
                        bridge.push_back(f);
                    }
                    // biconnected component (2-vertex-connected)
                    vector<pair<int, int>> t;
                    do {
                        t.push_back(s.top());
                        s.pop();
                    } while (t.back() != f);
                    bcc.push_back(t);
                }
            } else if (*w != p && dfn[*w] < dfn[v]) {
                s.push(f);
                low[v] = min(low[v], dfn[*w]);
            }
        }
    }

    void gao() {
        cut.clear();
        bridge.clear();
        bcc.clear();

        timestamp = 0;
        stack<pair<int, int>>().swap(s);
        fill(dfn.begin(), dfn.end(), -1);

        for (int i = 0; i < n; ++i) {
            if (dfn[i] == -1) {
                dfs(i, -1);
            }
        }
    }
};

struct BridgeBlockTree {
    Tarjan<MAXN> bcc;
    DisjointSet<MAXN> ds;
    vector<int> e[MAXN];

    void init(int n) {
        bcc.init(n);
        ds.init(n);
    }

    void add(int a, int b) {
        bcc.add(a, b);
    }

    void gao() {
        bcc.gao();
        for (const auto &i : bcc.bcc) {
            if (i.size() > 1) {
                for (const auto &j : i) {
                    ds.setp(j.first, j.second);
                }
            }
        }
        for (const auto &i : bcc.bridge) {
            int a = ds.getp(i.first);
            int b = ds.getp(i.second);
            e[a].push_back(b);
            e[b].push_back(a);
        }
    }

    int id(int v) {
        return ds.getp(v);
    }
};
#line 1 "src/watashi/bcc.hpp"
#include <algorithm>
#include <stack>
#include <utility>
#include <vector>

using namespace std;

// TODO: cannot handle duplicate edges
struct Tarjan {
    int n;
    vector<vector<int>> e;

    vector<int> cut;
    vector<pair<int, int>> bridge;
    vector<vector<pair<int, int>>> bcc;

    void init(int n) {
        this->n = n;
        e.clear();
        e.resize(n);
        dfn.resize(n);
        low.resize(n);
    }

    void add(int a, int b) {
        // assert(find(e[a].begin(), e[a].end(), b) == e[a].end());
        e[a].push_back(b);
        e[b].push_back(a);
    }

    vector<int> dfn, low;
    int timestamp;
    stack<pair<int, int>> s;

    void dfs(int v, int p) {
        int part = p == -1 ? 0 : 1;
        dfn[v] = low[v] = timestamp++;
        for (vector<int>::const_iterator w = e[v].begin(); w != e[v].end(); ++w) {
            pair<int, int> f = make_pair(min(v, *w), max(v, *w));
            if (dfn[*w] == -1) {
                s.push(f);
                dfs(*w, v);
                low[v] = min(low[v], low[*w]);
                if (dfn[v] <= low[*w]) {
                    // articulation point
                    if (++part == 2) {
                        cut.push_back(v);
                    }
                    // articulation edge
                    if (dfn[v] < low[*w]) {
                        bridge.push_back(f);
                    }
                    // biconnected component (2-vertex-connected)
                    vector<pair<int, int>> t;
                    do {
                        t.push_back(s.top());
                        s.pop();
                    } while (t.back() != f);
                    bcc.push_back(t);
                }
            } else if (*w != p && dfn[*w] < dfn[v]) {
                s.push(f);
                low[v] = min(low[v], dfn[*w]);
            }
        }
    }

    void gao() {
        cut.clear();
        bridge.clear();
        bcc.clear();

        timestamp = 0;
        stack<pair<int, int>>().swap(s);
        fill(dfn.begin(), dfn.end(), -1);

        for (int i = 0; i < n; ++i) {
            if (dfn[i] == -1) {
                dfs(i, -1);
            }
        }
    }
};

struct BridgeBlockTree {
    Tarjan<MAXN> bcc;
    DisjointSet<MAXN> ds;
    vector<int> e[MAXN];

    void init(int n) {
        bcc.init(n);
        ds.init(n);
    }

    void add(int a, int b) {
        bcc.add(a, b);
    }

    void gao() {
        bcc.gao();
        for (const auto &i : bcc.bcc) {
            if (i.size() > 1) {
                for (const auto &j : i) {
                    ds.setp(j.first, j.second);
                }
            }
        }
        for (const auto &i : bcc.bridge) {
            int a = ds.getp(i.first);
            int b = ds.getp(i.second);
            e[a].push_back(b);
            e[b].push_back(a);
        }
    }

    int id(int v) {
        return ds.getp(v);
    }
};
Back to top page