cplib-cpp

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

View the Project on GitHub hitonanode/cplib-cpp

:heavy_check_mark: graph/test/incremental-bridge-connectivity.test.cpp

Depends on

Code

#include "../incremental_bridge_connectivity.hpp"
#include <algorithm>
#include <iostream>
#include <vector>
#define PROBLEM "https://judge.yosupo.jp/problem/two_edge_connected_components"
using namespace std;

int main() {
    cin.tie(nullptr), ios::sync_with_stdio(false);

    int V, E;
    cin >> V >> E;
    IncrementalBridgeConnectivity graph(V);
    while (E--) {
        int s, t;
        cin >> s >> t;
        graph.add_edge(s, t);
    }

    vector<vector<int>> ret(V);
    for (int i = 0; i < V; i++) { ret[graph.find(i)].emplace_back(i); }
    int K = count_if(ret.begin(), ret.end(), [](const vector<int> &v) { return v.size() > 0; });
    cout << K << '\n';
    for (const auto &vec : ret) {
        if (vec.size()) {
            cout << vec.size();
            for (auto x : vec) { cout << ' ' << x; }
            cout << '\n';
        }
    }
}
#line 2 "unionfind/unionfind.hpp"
#include <algorithm>
#include <numeric>
#include <utility>
#include <vector>

// CUT begin
// UnionFind Tree (0-indexed), based on size of each disjoint set
struct UnionFind {
    std::vector<int> par, cou;
    UnionFind(int N = 0) : par(N), cou(N, 1) { iota(par.begin(), par.end(), 0); }
    int find(int x) { return (par[x] == x) ? x : (par[x] = find(par[x])); }
    bool unite(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) return false;
        if (cou[x] < cou[y]) std::swap(x, y);
        par[y] = x, cou[x] += cou[y];
        return true;
    }
    int count(int x) { return cou[find(x)]; }
    bool same(int x, int y) { return find(x) == find(y); }
    std::vector<std::vector<int>> groups() {
        std::vector<std::vector<int>> ret(par.size());
        for (int i = 0; i < int(par.size()); ++i) ret[find(i)].push_back(i);
        ret.erase(std::remove_if(ret.begin(), ret.end(),
                                 [&](const std::vector<int> &v) { return v.empty(); }),
                  ret.end());
        return ret;
    }
};
#line 3 "graph/incremental_bridge_connectivity.hpp"
#include <cassert>
#line 5 "graph/incremental_bridge_connectivity.hpp"
#include <unordered_set>
#line 7 "graph/incremental_bridge_connectivity.hpp"

// CUT begin
// Incremental Bridge-Connectivity
// two-edge-connected components
// Reference: <https://scrapbox.io/data-structures/Incremental_Bridge-Connectivity>
//            <https://ei1333.github.io/library/graph/connected-components/incremental-bridge-connectivity.cpp>
struct IncrementalBridgeConnectivity {
    int V;
    int nb_bridge;
    UnionFind con, bicon;
    std::vector<int> bbf;

    int _bicon_par(int x) { return bbf[x] == -1 ? -1 : bicon.find(bbf[x]); }
    int _lca(int x, int y) {
        std::unordered_set<int> us;
        while (true) {
            if (x != -1) {
                if (!us.insert(x).second) { return x; }
                x = _bicon_par(x);
            }
            std::swap(x, y);
        }
    }
    void _compress(int now, int lca) {
        while (bicon.find(now) != bicon.find(lca)) {
            int nxt = _bicon_par(now);
            bbf[now] = bbf[lca], bicon.unite(now, lca), now = nxt, nb_bridge--;
        }
    }

    IncrementalBridgeConnectivity(int v = 0) : V(v), nb_bridge(0), con(v), bicon(v), bbf(v, -1) {}

    void add_edge(int u, int v) {
        assert(u >= 0 and u < V);
        assert(v >= 0 and v < V);
        u = bicon.find(u), v = bicon.find(v);
        if (con.find(u) == con.find(v)) {
            int lca = _lca(u, v);
            _compress(u, lca), _compress(v, lca);
        } else {
            if (con.count(u) > con.count(v)) std::swap(u, v);
            for (int now = u, pre = v; now != -1;) {
                int nxt = _bicon_par(now);
                bbf[now] = pre, pre = now, now = nxt;
            }
            con.unite(u, v), nb_bridge++;
        }
    }
    int count_bridge() const { return nb_bridge; }
    bool two_edge_connected(int x, int y) { return bicon.same(x, y); }
    int find(int x) { return bicon.find(x); }
};
#line 3 "graph/test/incremental-bridge-connectivity.test.cpp"
#include <iostream>
#line 5 "graph/test/incremental-bridge-connectivity.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/two_edge_connected_components"
using namespace std;

int main() {
    cin.tie(nullptr), ios::sync_with_stdio(false);

    int V, E;
    cin >> V >> E;
    IncrementalBridgeConnectivity graph(V);
    while (E--) {
        int s, t;
        cin >> s >> t;
        graph.add_edge(s, t);
    }

    vector<vector<int>> ret(V);
    for (int i = 0; i < V; i++) { ret[graph.find(i)].emplace_back(i); }
    int K = count_if(ret.begin(), ret.end(), [](const vector<int> &v) { return v.size() > 0; });
    cout << K << '\n';
    for (const auto &vec : ret) {
        if (vec.size()) {
            cout << vec.size();
            for (auto x : vec) { cout << ' ' << x; }
            cout << '\n';
        }
    }
}
Back to top page