This documentation is automatically generated by online-judge-tools/verification-helper
#include "graph/incremental_bridge_connectivity.hpp"
#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); }
};