Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions library/dsu/kruskal_tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
struct kr_tree {
int id;
vi p;
vector<vi> adj;
kr_tree(int n): id(n), p(2 * n, -1), adj(2 * n) {}
vector<vi> g;
kr_tree(int n): id(n), p(2 * n, -1), g(2 * n) {}
int f(int u) { return p[u] < 0 ? u : p[u] = f(p[u]); }
bool join(int u, int v) {
if ((u = f(u)) == (v = f(v))) return 0;
return adj[p[u] = p[v] = id++] = {u, v}, 1;
return g[p[u] = p[v] = id++] = {u, v}, 1;
}
};
26 changes: 13 additions & 13 deletions library/flow/min_cost_max_flow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ struct mcmf {
};
int n;
vector<edge> e;
vector<vi> adj;
mcmf(int n): n(n), adj(n) {}
vector<vi> g;
mcmf(int n): n(n), g(n) {}
void add_edge(int u, int v, ll cap, ll cost) {
edge e1 = {u, v, cap, cost, 0, sz(adj[v])};
edge e2 = {v, u, 0, -cost, 0, sz(adj[u])};
adj[u].push_back(sz(e));
edge e1 = {u, v, cap, cost, 0, sz(g[v])};
edge e2 = {v, u, 0, -cost, 0, sz(g[u])};
g[u].push_back(sz(e));
e.push_back(e1);
adj[v].push_back(sz(e));
g[v].push_back(sz(e));
e.push_back(e2);
}
array<ll, 2> get_flow(int s, int t, ll total_flow) {
Expand All @@ -39,8 +39,8 @@ struct mcmf {
int u = q[qh++];
id[u] = 2;
if (qh == n) qh = 0;
rep(i, 0, sz(adj[u])) {
edge& r = e[adj[u][i]];
rep(i, 0, sz(g[u])) {
edge& r = e[g[u][i]];
if (r.flow < r.cap && d[u] + r.cost < d[r.v]) {
d[r.v] = d[u] + r.cost;
if (id[r.v] == 0) {
Expand All @@ -61,14 +61,14 @@ struct mcmf {
for (int u = t; u != s; u = p[u]) {
int pv = p[u], pr = p_edge[u];
addflow = min(addflow,
e[adj[pv][pr]].cap - e[adj[pv][pr]].flow);
e[g[pv][pr]].cap - e[g[pv][pr]].flow);
}
for (int u = t; u != s; u = p[u]) {
int pv = p[u], pr = p_edge[u],
r = e[adj[pv][pr]].back;
e[adj[pv][pr]].flow += addflow;
e[adj[u][r]].flow -= addflow;
cost += e[adj[pv][pr]].cost * addflow;
r = e[g[pv][pr]].back;
e[g[pv][pr]].flow += addflow;
e[g[u][r]].flow -= addflow;
cost += e[g[pv][pr]].cost * addflow;
}
flow += addflow;
}
Expand Down
18 changes: 9 additions & 9 deletions library/graphs/bcc_callback.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
//! https://cp-algorithms.com/graph/cutpoints.html
//! @code
//! {
//! vector<vi> adj(n);
//! vector<vi> g(n);
//! DSU dsu(n);
//! vector<bool> seen(n);
//! bcc(adj, [&](const vi& nodes) {
//! bcc(g, [&](const vi& nodes) {
//! int count_edges = 0;
//! rep (i, 0, sz(nodes) - 1) {
//! seen[nodes[i]] = 1;
//! for (int u : adj[nodes[i]]) if (!seen[u]) {
//! for (int u : g[nodes[i]]) if (!seen[u]) {
//! // edge nodes[i] <=> u is in current BCC
//! count_edges++;
//! }
Expand All @@ -22,15 +22,15 @@
//! });
//! vector<basic_string<int>> bridge_tree(n);
//! rep (i, 0, n)
//! for (int u : adj[i])
//! for (int u : g[i])
//! if (dsu.f(i) != dsu.f(u))
//! bridge_tree[dsu.f(i)] += dsu.f(u);
//! }
//!
//! vector<basic_string<int>> adj(n);
//! vector<basic_string<int>> g(n);
//! vector<basic_string<int>> block_vertex_tree(2 * n);
//! int bcc_id = n;
//! bcc(adj, [&](const vi& nodes) {
//! bcc(g, [&](const vi& nodes) {
//! for (int u : nodes) {
//! block_vertex_tree[u] += bcc_id;
//! block_vertex_tree[bcc_id] += u;
Expand All @@ -41,12 +41,12 @@
//! callback not called on components with a single node
//! @time O(n + m)
//! @space O(n)
void bcc(const auto& adj, auto f) {
int n = sz(adj), q = 0, s = 0;
void bcc(const auto& g, auto f) {
int n = sz(g), q = 0, s = 0;
vi t(n), st(n);
auto dfs = [&](auto&& dfs, int u) -> int {
int l = t[u] = ++q;
for (int v : adj[u]) {
for (int v : g[u]) {
int siz = s, lu = 0;
l = min(l, t[v] ?: (lu = dfs(dfs, st[s++] = v)));
if (lu >= t[u]) {
Expand Down
10 changes: 5 additions & 5 deletions library/graphs/dijkstra.hpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
#pragma once
//! @code
//! vector<basic_string<array<int, 2>>> adj(n);
//! auto d = dijkstra(adj, source);
//! vector<basic_string<array<int, 2>>> g(n);
//! auto d = dijkstra(g, source);
//! @endcode
//! d[v] = min dist from source->..->v
//! @time O(n + (m log m))
//! @space O(n + m)
vector<ll> dijkstra(const auto& adj, int s) {
vector<ll> dijkstra(const auto& g, int s) {
using p = pair<ll, int>;
priority_queue<p, vector<p>, greater<>> pq;
pq.emplace(0, s);
vector<ll> d(sz(adj), LLONG_MAX);
vector<ll> d(sz(g), LLONG_MAX);
while (!empty(pq)) {
auto [d_v, v] = pq.top();
pq.pop();
if (d[v] != LLONG_MAX) continue;
d[v] = d_v;
for (auto [u, w] : adj[v]) pq.emplace(w + d_v, u);
for (auto [u, w] : g[v]) pq.emplace(w + d_v, u);
}
return d;
}
14 changes: 7 additions & 7 deletions library/graphs/euler_path.hpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
#pragma once
//! @code
//! vector<basic_string<array<int, 2>>> adj(n);
//! vector<basic_string<array<int, 2>>> g(n);
//! vector<pii> edges(m);
//! rep(i, 0, m) {
//! int u, v;
//! cin >> u >> v;
//! u--, v--;
//! adj[u] += {v, i};
//! g[u] += {v, i};
//! edges[i] = {u, v};
//! }
//! vector<pii> path = euler_path(adj, m, source);
//! vector<pii> path = euler_path(g, m, source);
//! @endcode
//! @time O(n + m)
//! @space O(n + m)
vector<pii> euler_path(auto& adj, int m, int s) {
vector<pii> euler_path(auto& g, int m, int s) {
vi vis(m);
vector<pii> path;
auto dfs = [&](auto&& dfs, int u, int eu) -> void {
while (!empty(adj[u])) {
auto [v, ev] = adj[u].back();
adj[u].pop_back();
while (!empty(g[u])) {
auto [v, ev] = g[u].back();
g[u].pop_back();
if (!vis[ev]) vis[ev] = 1, dfs(dfs, v, ev);
}
path.emplace_back(u, eu);
Expand Down
16 changes: 8 additions & 8 deletions library/graphs/hopcroft_karp.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#pragma once
//! https://github.com/foreverbell/acm-icpc-cheat-sheet/blob/master/src/graph-algorithm/hopcroft-karp.cpp
//! @code
//! vector<basic_string<int>> adj(lsz);
//! adj[l] += r; // add edge l <-> r
//! vector<basic_string<int>> g(lsz);
//! g[l] += r; // add edge l <-> r
//! // 0<=l<lsz; 0<=r<rsz
//! auto [matching_size, to_r, to_l,
//! mvc_l, mvc_r] = hopcroft_karp(adj, rsz);
//! mvc_l, mvc_r] = hopcroft_karp(g, rsz);
//! @endcode
//! l <-> to_r[l] in matching if to_r[l]!=-1
//! to_l[r] <-> r in matching if to_l[r]!=-1
Expand All @@ -17,9 +17,9 @@ struct hopcroft_karp {
int m_sz = 0;
vi to_r, to_l;
vector<bool> mvc_l, mvc_r;
hopcroft_karp(const auto& adj, int rsz):
to_r(sz(adj), -1), to_l(rsz, -1) {
int lsz = sz(adj);
hopcroft_karp(const auto& g, int rsz):
to_r(sz(g), -1), to_l(rsz, -1) {
int lsz = sz(g);
while (1) {
queue<int> q;
vi level(lsz, -1);
Expand All @@ -32,7 +32,7 @@ struct hopcroft_karp {
int u = q.front();
q.pop();
mvc_l[u] = 0;
for (int v : adj[u]) {
for (int v : g[u]) {
mvc_r[v] = 1;
int w = to_l[v];
if (w == -1) found = 1;
Expand All @@ -44,7 +44,7 @@ struct hopcroft_karp {
}
if (!found) break;
auto dfs = [&](auto&& dfs, int u) -> bool {
for (int v : adj[u]) {
for (int v : g[u]) {
int w = to_l[v];
if (w == -1 ||
(level[u] + 1 == level[w] && dfs(dfs, w))) {
Expand Down
10 changes: 5 additions & 5 deletions library/graphs/scc.hpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
#pragma once
//! https://github.com/kth-competitive-programming/kactl/blob/main/content/graph/SCC.h
//! @code
//! vector<basic_string<int>> adj(n);
//! auto [num_sccs, scc_id] = scc(adj);
//! vector<basic_string<int>> g(n);
//! auto [num_sccs, scc_id] = scc(g);
//! @endcode
//! scc_id[u] = id, 0<=id<num_sccs
//! for each edge u -> v: scc_id[u] >= scc_id[v]
//! @time O(n + m)
//! @space O(n)
auto scc(const auto& adj) {
int n = sz(adj), num_sccs = 0, q = 0, s = 0;
auto scc(const auto& g) {
int n = sz(g), num_sccs = 0, q = 0, s = 0;
vi scc_id(n, -1), tin(n), st(n);
auto dfs = [&](auto&& dfs, int u) -> int {
int low = tin[u] = ++q;
st[s++] = u;
for (int v : adj[u])
for (int v : g[u])
if (scc_id[v] < 0)
low = min(low, tin[v] ?: dfs(dfs, v));
if (tin[u] == low) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,30 @@
//! SCCs)
//!
//! @code
//! auto [num_sccs, scc_id] = scc(adj);
//! vector<pii> edges = extra_edges(adj,
//! auto [num_sccs, scc_id] = scc(g);
//! vector<pii> edges = extra_edges(g,
//! num_sccs, scc_id);
//! @endcode
//! @param adj,num_sccs,scc_id directed graph and its SCCs
//! @param g,num_sccs,scc_id directed graph and its SCCs
//! @returns directed edge list: edges[i][0] -> edges[i][1]
//! @time O(n + m)
//! @space An O(n) edge list is allocated and returned, but
//! multiple O(n + m) vectors are allocated temporarily
vector<pii> extra_edges(const auto& adj, int num_sccs,
vector<pii> extra_edges(const auto& g, int num_sccs,
const vi& scc_id) {
if (num_sccs == 1) return {};
int n = sz(adj);
vector<vi> scc_adj(num_sccs);
int n = sz(g);
vector<vi> scc_g(num_sccs);
vector<bool> zero_in(num_sccs, 1);
rep(i, 0, n) for (int v : adj[i]) {
rep(i, 0, n) for (int v : g[i]) {
if (scc_id[i] == scc_id[v]) continue;
scc_adj[scc_id[i]].push_back(scc_id[v]);
scc_g[scc_id[i]].push_back(scc_id[v]);
zero_in[scc_id[v]] = 0;
}
vector<bool> vis(num_sccs);
auto dfs = [&](auto&& dfs, int u) {
if (empty(scc_adj[u])) return u;
for (int v : scc_adj[u])
if (empty(scc_g[u])) return u;
for (int v : scc_g[u])
if (!vis[v]) {
vis[v] = 1;
int zero_out = dfs(dfs, v);
Expand All @@ -49,7 +49,7 @@ vector<pii> extra_edges(const auto& adj, int num_sccs,
}
rep(i, 1, sz(edges))
swap(edges[i].first, edges[i - 1].first);
rep(i, 0, num_sccs) if (empty(scc_adj[i]) && !vis[i]) {
rep(i, 0, num_sccs) if (empty(scc_g[i]) && !vis[i]) {
if (!empty(in_unused)) {
edges.emplace_back(i, in_unused.back());
in_unused.pop_back();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@ vi offline_incremental_scc(vector<array<int, 2>> eds,
int m = sz(eds);
vi ids(n, -1), joins(m, m), idx(m), vs(n), scc_id;
iota(all(idx), 0);
vector<vi> adj;
vector<vi> g;
auto dnc = [&](auto&& dnc, auto el, auto er, int tl,
int tr) {
adj.clear();
g.clear();
int mid = midpoint(tl, tr);
for (auto it = el; it != er; it++) {
auto& [u, v] = eds[*it];
for (int w : {u, v}) {
if (ids[w] != -1) continue;
ids[w] = sz(adj);
vs[sz(adj)] = w;
adj.emplace_back();
ids[w] = sz(g);
vs[sz(g)] = w;
g.emplace_back();
}
u = ids[u], v = ids[v];
if (*it <= mid) adj[u].push_back(v);
if (*it <= mid) g[u].push_back(v);
}
rep(i, 0, sz(adj)) ids[vs[i]] = -1;
scc_id = scc(adj).second;
rep(i, 0, sz(g)) ids[vs[i]] = -1;
scc_id = scc(g).second;
auto split = partition(el, er, [&](int i) {
return scc_id[eds[i][0]] == scc_id[eds[i][1]];
});
Expand Down
12 changes: 6 additions & 6 deletions library/graphs/uncommon/block_vertex_tree.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#pragma once
#include "cuts.hpp"
//! @code
//! vector<basic_string<array<int, 2>>> adj(n);
//! auto [num_bccs, bcc_id, is_cut] = cuts(adj, m);
//! auto bvt = block_vertex_tree(adj, num_bccs, bcc_id);
//! vector<basic_string<array<int, 2>>> g(n);
//! auto [num_bccs, bcc_id, is_cut] = cuts(g, m);
//! auto bvt = block_vertex_tree(g, num_bccs, bcc_id);
//!
//! //to loop over each unique bcc containing a node u:
//! for (int bccid : bvt[v]) {
Expand All @@ -16,13 +16,13 @@
//! [n, n + num_bccs) are BCC nodes
//! @time O(n + m)
//! @time O(n)
auto block_vertex_tree(const auto& adj, int num_bccs,
auto block_vertex_tree(const auto& g, int num_bccs,
const vi& bcc_id) {
int n = sz(adj);
int n = sz(g);
vector<vi> bvt(n + num_bccs);
vector<bool> vis(num_bccs);
rep(i, 0, n) {
for (auto [_, e_id] : adj[i]) {
for (auto [_, e_id] : g[i]) {
int bccid = bcc_id[e_id];
if (!vis[bccid]) {
vis[bccid] = 1;
Expand Down
10 changes: 5 additions & 5 deletions library/graphs/uncommon/bridge_tree.hpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
#pragma once
#include "bridges.hpp"
//! @code
//! vector<basic_string<array<int, 2>>> adj(n);
//! auto [num_ccs, br_id, is_br] = bridges(adj, m);
//! auto bt = bridge_tree(adj, num_ccs, br_id, is_br);
//! vector<basic_string<array<int, 2>>> g(n);
//! auto [num_ccs, br_id, is_br] = bridges(g, m);
//! auto bt = bridge_tree(g, num_ccs, br_id, is_br);
//! @endcode
//! @time O(n + m)
//! @space O(n)
auto bridge_tree(const auto& adj, int num_ccs,
auto bridge_tree(const auto& g, 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 (
rep(i, 0, sz(g)) for (auto [u, e_id] : g[i]) if (
is_br[e_id]) tree[br_id[i]]
.push_back(br_id[u]);
return tree;
Expand Down
Loading
Loading