Skip to content
Merged
6 changes: 3 additions & 3 deletions library/contest/random.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
//! uint64_t x1 = rng();
//! mt19937 rng; // fixed seed for debugging
//! int x2 = rnd(0, 1); //random number in [0,1]
//! ll x3 = rnd<ll>(1, 1e18);
//! ll x3 = rnd(ll(1), ll(1e18));
//! @endcode
mt19937 rng(
chrono::steady_clock::now().time_since_epoch().count());
template<class T> T rnd(T l, T r) {
auto rnd(auto l, auto r) {
assert(l <= r);
return uniform_int_distribution<T>(l, r)(rng);
return uniform_int_distribution(l, r)(rng);
}
6 changes: 2 additions & 4 deletions library/data_structures/dsu/range_parallel_dsu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@
struct rp_dsu {
vector<UF> ufs;
rp_dsu(int n): ufs(bit_width(unsigned(n)), UF(n)) {}
template<class F>
void join(int l1, int l2, int len, const F& f) {
void join(int l1, int l2, int len, const auto& f) {
if (len == 0) return;
int lg = __lg(len);
join_impl(lg, l1, l2, f);
join_impl(lg, l1 + len - (1 << lg),
l2 + len - (1 << lg), f);
}
template<class F>
void join_impl(int lvl, int u, int v, const F& f) {
void join_impl(int lvl, int u, int v, const auto& f) {
if (lvl == 0) {
u = ufs[0].find(u);
v = ufs[0].find(v);
Expand Down
11 changes: 4 additions & 7 deletions library/data_structures/seg_tree_uncommon/find_first.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,11 @@
//! such element exists then `r` is returned
//! @time O(log(n))
//! @space O(log(n)) for recursion stack
template<class F>
int find_first(int l, int r, const F& f) {
int find_first(int l, int r, const auto& f) {
return find_first_in_range(l, r, f, 0, n, 1);
}
//! invariant: f(tree[v], tl, tr) is 1
template<class F>
int find_first_in_subtree(const F& f, int tl, int tr,
int find_first_in_subtree(const auto& f, int tl, int tr,
int v) {
if (v >= n) return tl;
int tm = split(tl, tr);
Expand All @@ -40,9 +38,8 @@ int find_first_in_subtree(const F& f, int tl, int tr,
return find_first_in_subtree(f, tl, tm, 2 * v);
return find_first_in_subtree(f, tm, tr, 2 * v + 1);
}
template<class F>
int find_first_in_range(int l, int r, const F& f, int tl,
int tr, int v) {
int find_first_in_range(int l, int r, const auto& f,
int tl, int tr, int v) {
if (r <= tl || tr <= l) return r;
if (l <= tl && tr <= r)
return f(tree[v], tl, tr)
Expand Down
8 changes: 3 additions & 5 deletions library/data_structures/seg_tree_uncommon/find_last.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,11 @@
//! such element exists then (l - 1) is returned
//! @time O(log(n))
//! @space O(log(n)) for recursion stack
template<class F> int find_last(int l, int r, const F& f) {
int find_last(int l, int r, const auto& f) {
return find_last_in_range(l, r, f, 0, n, 1);
}
//! invariant: f(tree[v], tl, tr) is 1
template<class F>
int find_last_in_subtree(const F& f, int tl, int tr,
int find_last_in_subtree(const auto& f, int tl, int tr,
int v) {
if (v >= n) return tl;
int tm = split(tl, tr);
Expand All @@ -39,8 +38,7 @@ int find_last_in_subtree(const F& f, int tl, int tr,
return find_last_in_subtree(f, tm, tr, 2 * v + 1);
return find_last_in_subtree(f, tl, tm, 2 * v);
}
template<class F>
int find_last_in_range(int l, int r, const F& f, int tl,
int find_last_in_range(int l, int r, const auto& f, int tl,
int tr, int v) {
if (r <= tl || tr <= l) return l - 1;
if (l <= tl && tr <= r)
Expand Down
21 changes: 11 additions & 10 deletions library/graphs/bridges_cuts/block_vertex_tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
//! @code
//! {
//! vector<vector<pii>> adj(n);
//! cuts cc(adj, m);
//! vector<vi> bvt = block_vertex_tree(adj, cc);
//! auto [num_bccs, bcc_id, is_cut] = cuts(adj, m);
//! vector<vi> bvt = block_vertex_tree(adj,
//! num_bccs, bcc_id);
//! }
//! vector<basic_string<array<int, 2>>> adj(n);
//! cuts cc(adj, m);
//! vector<vi> bvt = block_vertex_tree(adj, cc);
//! auto [num_bccs, bcc_id, is_cut] = cuts(adj, m);
//! vector<vi> bvt = block_vertex_tree(adj,
//! num_bccs, bcc_id);
//!
//! //to loop over each unique bcc containing a node u:
//! for (int bccid : bvt[v]) {
Expand All @@ -21,15 +23,14 @@
//! [n, n + num_bccs) are BCC nodes
//! @time O(n + m)
//! @time O(n)
template<class G>
vector<vi> block_vertex_tree(const G& adj,
const cuts<G>& cc) {
vector<vi> block_vertex_tree(const auto& adj, int num_bccs,
const vi& bcc_id) {
int n = sz(adj);
vector<vi> bvt(n + cc.num_bccs);
vector<bool> vis(cc.num_bccs);
vector<vi> bvt(n + num_bccs);
vector<bool> vis(num_bccs);
rep(i, 0, n) {
for (auto [_, e_id] : adj[i]) {
int bccid = cc.bcc_id[e_id];
int bccid = bcc_id[e_id];
if (!vis[bccid]) {
vis[bccid] = 1;
bvt[i].push_back(bccid + n);
Expand Down
21 changes: 11 additions & 10 deletions library/graphs/bridges_cuts/bridge_tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,22 @@
//! @code
//! {
//! vector<vector<pii>> adj(n);
//! bridges br(adj, m);
//! vector<vi> bt = bridge_tree(adj, br);
//! auto [num_ccs, br_id, is_br] = bridges(adj, m);
//! vector<vi> bt = bridge_tree(adj,
//! num_ccs, br_id, is_br);
//! }
//! vector<basic_string<array<int, 2>>> adj(n);
//! bridges br(adj, m);
//! vector<vi> bt = bridge_tree(adj, br);
//! auto [num_ccs, br_id, is_br] = bridges(adj, m);
//! vector<vi> bt = bridge_tree(adj,
//! num_ccs, br_id, is_br);
//! @endcode
//! @time O(n + m)
//! @space O(n)
template<class G>
vector<vi> bridge_tree(const G& adj,
const bridges<G>& br) {
vector<vi> tree(br.num_ccs);
vector<vi> bridge_tree(const auto& adj, int num_ccs,
const vi& br_id, const vi& is_br) {
vector<vi> tree(num_ccs);
rep(i, 0, sz(adj)) for (auto [u, e_id] : adj[i]) if (
br.is_bridge[e_id]) tree[br.br_id[i]]
.push_back(br.br_id[u]);
is_br[e_id]) tree[br_id[i]]
.push_back(br_id[u]);
return tree;
}
53 changes: 23 additions & 30 deletions library/graphs/bridges_cuts/bridges.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! @code
//! {
//! vector<vector<pii>> adj(n);
//! auto [num_ccs, is_bridge, br_id] = bridges(adj, m);
//! auto [num_ccs, br_id, is_br] = bridges(adj, m);
//! }
//! vector<basic_string<array<int, 2>>> adj(n);
//! rep (i, 0, m) {
Expand All @@ -13,36 +13,29 @@
//! adj[u].push_back({v, i});
//! adj[v].push_back({u, i});
//! }
//! auto [num_ccs, is_bridge, br_id] = bridges(adj, m);
//! auto [num_ccs, br_id, is_br] = bridges(adj, m);
//! @endcode
//! is_bridge[edge id] = 1 iff bridge edge
//! is_br[edge id] = 1 iff bridge edge
//! br_id[v] = id, 0<=id<num_ccs
//! @time O(n + m)
//! @space O(n + m)
template<class G> struct bridges {
int num_ccs = 0;
vector<bool> is_bridge;
vi br_id;
bridges(const G& adj, int m):
is_bridge(m), br_id(sz(adj), -1) {
int n = sz(adj), timer = 1;
vi tin(n), st;
auto dfs = [&](auto&& self, int v, int p_id) -> int {
int low = tin[v] = timer++, siz = sz(st);
st.push_back(v);
for (auto [u, e_id] : adj[v]) {
if (e_id == p_id) continue;
if (!tin[u]) low = min(low, self(self, u, e_id));
low = min(low, tin[u]);
}
if (tin[v] == low) {
if (p_id != -1) is_bridge[p_id] = 1;
rep(i, siz, sz(st)) br_id[st[i]] = num_ccs;
st.resize(siz);
num_ccs++;
}
return low;
};
rep(i, 0, n) if (!tin[i]) dfs(dfs, i, -1);
}
};
auto bridges(const auto& adj, int m) {
int n = sz(adj), num_ccs = 0, timer = 0;
vi br_id(n, -1), is_br(m), tin(n), st;
auto dfs = [&](auto&& self, int v, int p_id) -> int {
int low = tin[v] = ++timer, siz = sz(st);
st.push_back(v);
for (auto [u, e_id] : adj[v])
if (e_id != p_id && br_id[u] < 0)
low = min(low, tin[u] ?: self(self, u, e_id));
if (tin[v] == low) {
if (p_id != -1) is_br[p_id] = 1;
rep(i, siz, sz(st)) br_id[st[i]] = num_ccs;
st.resize(siz);
num_ccs++;
}
return low;
};
rep(i, 0, n) if (!tin[i]) dfs(dfs, i, -1);
return tuple{num_ccs, br_id, is_br};
}
67 changes: 31 additions & 36 deletions library/graphs/bridges_cuts/cuts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! @code
//! {
//! vector<vector<pii>> adj(n);
//! auto [num_bccs, is_cut, bcc_id] = cuts(adj, m);
//! auto [num_bccs, bcc_id, is_cut] = cuts(adj, m);
//! }
//! vector<basic_string<array<int, 2>>> adj(n);
//! rep (i, 0, m) {
Expand All @@ -14,45 +14,40 @@
//! adj[u].push_back({v, i});
//! adj[v].push_back({u, i});
//! }
//! auto [num_bccs, is_cut, bcc_id] = cuts(adj, m);
//! auto [num_bccs, bcc_id, is_cut] = cuts(adj, m);
//! @endcode
//! is_cut[v] = 1 iff cut node
//! bcc_id[edge id] = id, 0<=id<num_bccs
//! @time O(n + m)
//! @space O(n + m)
template<class G> struct cuts {
int num_bccs = 0;
vector<bool> is_cut;
vi bcc_id;
cuts(const G& adj, int m):
is_cut(sz(adj)), bcc_id(m, -1) {
int n = sz(adj), timer = 1;
vi tin(n), st;
auto dfs = [&](auto&& self, int v, int p_id) -> int {
int low = tin[v] = timer++, deg = 0;
for (auto [u, e_id] : adj[v]) {
assert(v != u);
if (e_id == p_id) continue;
if (!tin[u]) {
int siz = sz(st);
st.push_back(e_id);
int low_ch = self(self, u, e_id);
if (low_ch >= tin[v]) {
is_cut[v] = 1;
rep(i, siz, sz(st)) bcc_id[st[i]] = num_bccs;
st.resize(siz);
num_bccs++;
}
low = min(low, low_ch);
deg++;
} else if (tin[u] < tin[v]) {
st.push_back(e_id);
low = min(low, tin[u]);
auto cuts(const auto& adj, int m) {
int n = sz(adj), num_bccs = 0, timer = 0;
vi bcc_id(m, -1), is_cut(n), tin(n), st;
auto dfs = [&](auto&& self, int v, int p_id) -> int {
int low = tin[v] = ++timer, deg = 0;
for (auto [u, e_id] : adj[v]) {
assert(v != u);
if (e_id == p_id) continue;
if (!tin[u]) {
int siz = sz(st);
st.push_back(e_id);
int low_ch = self(self, u, e_id);
if (low_ch >= tin[v]) {
is_cut[v] = 1;
rep(i, siz, sz(st)) bcc_id[st[i]] = num_bccs;
st.resize(siz);
num_bccs++;
}
low = min(low, low_ch);
deg++;
} else if (tin[u] < tin[v]) {
st.push_back(e_id);
low = min(low, tin[u]);
}
if (p_id == -1) is_cut[v] = (deg > 1);
return low;
};
rep(i, 0, n) if (!tin[i]) dfs(dfs, i, -1);
}
};
}
if (p_id == -1) is_cut[v] = (deg > 1);
return low;
};
rep(i, 0, n) if (!tin[i]) dfs(dfs, i, -1);
return tuple{num_bccs, bcc_id, is_cut};
}
3 changes: 1 addition & 2 deletions library/graphs/complement_graph_ccs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
//! cc in the compliment graph
//! @time O(n + m)
//! @space O(n)
template<class G>
vi get_complement_graph_ccs(const G& adj) {
vi get_complement_graph_ccs(const auto& adj) {
int n = sz(adj);
vi cc_id(n), unseen(n);
iota(all(unseen), 0);
Expand Down
3 changes: 1 addition & 2 deletions library/graphs/dijkstra.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
//! d[v] = min dist from source->..->v
//! @time O(n + (m log m))
//! @space O(n + m)
template<class G>
vector<ll> dijkstra(const G& adj, int s) {
vector<ll> dijkstra(const auto& adj, int s) {
using p = pair<ll, int>;
priority_queue<p, vector<p>, greater<>> pq;
pq.emplace(0, s);
Expand Down
3 changes: 1 addition & 2 deletions library/graphs/enumerate_triangles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
//! @endcode
//! @time O(n + m ^ (3/2))
//! @space O(n + m)
template<class F>
void enumerate_triangles(const vector<pii>& edges, int n,
F f) {
auto f) {
vi deg(n);
for (auto [u, v] : edges) deg[u]++, deg[v]++;
vector<vi> adj(n);
Expand Down
4 changes: 2 additions & 2 deletions library/graphs/hopcroft_karp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
//! mvc_r[r] is 1 if r in Min Vertex Cover
//! @time O(n + m * sqrt(n)) n = lsz + rsz
//! @space O(n)
template<class G> struct hopcroft_karp {
struct hopcroft_karp {
int m_sz = 0;
vi to_r, to_l;
vector<bool> mvc_l, mvc_r;
hopcroft_karp(const G& adj, int rsz):
hopcroft_karp(const auto& adj, int rsz):
to_r(sz(adj), -1), to_l(rsz, -1) {
int lsz = sz(adj);
while (1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ vi offline_incremental_scc(vector<array<int, 2>> eds,
if (*it <= mid) adj[u].push_back(v);
}
for (int v : vs) ids[v] = -1;
auto scc_id = sccs(adj).scc_id;
auto scc_id = sccs(adj).second;
auto split = partition(el, er, [&](int i) {
return scc_id[eds[i][0]] == scc_id[eds[i][1]];
});
Expand Down
Loading
Loading