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/incremental_bridge_connectivity.hpp

Depends on

Verified with

Code

#pragma once
#include "../unionfind/unionfind.hpp"
#include <cassert>
#include <numeric>
#include <unordered_set>
#include <vector>

// 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 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); }
};
Back to top page