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
30 changes: 15 additions & 15 deletions library/graphs/bcc_callback.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,31 @@
//! int count_edges = 0;
//! rep (i, 0, sz(nodes) - 1) {
//! seen[nodes[i]] = 1;
//! for (int v : adj[nodes[i]]) if (!seen[v]) {
//! // edge nodes[i] <=> v is in current BCC
//! for (int u : adj[nodes[i]]) if (!seen[u]) {
//! // edge nodes[i] <=> u is in current BCC
//! count_edges++;
//! }
//! }
//! if (count_edges == 1) {
//! // nodes[0] <=> nodes[1] is a bridge
//! return;
//! }
//! for (int v : nodes) uf.join(v, nodes[0]);
//! for (int u : nodes) uf.join(u, nodes[0]);
//! });
//! vector<basic_string<int>> bridge_tree(n);
//! rep (i, 0, n)
//! for (int v : adj[i])
//! if (!uf.sameSet(i, v))
//! bridge_tree[uf.find(i)] += uf.find(v);
//! for (int u : adj[i])
//! if (!uf.sameSet(i, u))
//! bridge_tree[uf.find(i)] += uf.find(u);
//! }
//!
//! vector<basic_string<int>> adj(n);
//! vector<basic_string<int>> block_vertex_tree(2 * n);
//! int bcc_id = n;
//! bcc_callback(adj, [&](const vi& nodes) {
//! for (int v : nodes) {
//! block_vertex_tree[v] += bcc_id;
//! block_vertex_tree[bcc_id] += v;
//! for (int u : nodes) {
//! block_vertex_tree[u] += bcc_id;
//! block_vertex_tree[bcc_id] += u;
//! }
//! bcc_id++;
//! });
Expand All @@ -44,13 +44,13 @@
void bcc_callback(const auto& adj, auto f) {
int n = sz(adj), q = 0, s = 0;
vi t(n), st(n);
auto dfs = [&](auto&& self, int v) -> int {
int l = t[v] = ++q;
for (int u : adj[v]) {
auto dfs = [&](auto&& self, int u) -> int {
int l = t[u] = ++q;
for (int v : adj[u]) {
int siz = s, lu = 0;
l = min(l, t[u] ?: (lu = self(self, st[s++] = u)));
if (lu >= t[v]) {
st[s++] = v;
l = min(l, t[v] ?: (lu = self(self, st[s++] = v)));
if (lu >= t[u]) {
st[s++] = u;
f({siz + all(st) - n + s});
s = siz;
}
Expand Down
26 changes: 13 additions & 13 deletions library/graphs/hopcroft_karp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,31 +29,31 @@ struct hopcroft_karp {
mvc_l.assign(lsz, 1);
mvc_r.assign(rsz, 0);
while (!empty(q)) {
int v = q.front();
int u = q.front();
q.pop();
mvc_l[v] = 0;
for (int u : adj[v]) {
mvc_r[u] = 1;
int w = to_l[u];
mvc_l[u] = 0;
for (int v : adj[u]) {
mvc_r[v] = 1;
int w = to_l[v];
if (w == -1) found = 1;
else if (level[w] == -1) {
level[w] = level[v] + 1;
level[w] = level[u] + 1;
q.push(w);
}
}
}
if (!found) break;
auto dfs = [&](auto&& self, int v) -> bool {
for (int u : adj[v]) {
int w = to_l[u];
auto dfs = [&](auto&& self, int u) -> bool {
for (int v : adj[u]) {
int w = to_l[v];
if (w == -1 ||
(level[v] + 1 == level[w] && self(self, w))) {
to_r[v] = u;
to_l[u] = v;
(level[u] + 1 == level[w] && self(self, w))) {
to_r[u] = v;
to_l[v] = u;
return 1;
}
}
level[v] = INT_MAX;
level[u] = INT_MAX;
return 0;
};
rep(i, 0, lsz) m_sz +=
Expand Down
18 changes: 9 additions & 9 deletions library/graphs/scc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@
//! vector<basic_string<int>> adj(n);
//! auto [num_sccs, scc_id] = sccs(adj);
//! @endcode
//! scc_id[v] = id, 0<=id<num_sccs
//! 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 sccs(const auto& adj) {
int n = sz(adj), num_sccs = 0, q = 0, s = 0;
vi scc_id(n, -1), tin(n), st(n);
auto dfs = [&](auto&& self, int v) -> int {
int low = tin[v] = ++q;
st[s++] = v;
for (int u : adj[v])
if (scc_id[u] < 0)
low = min(low, tin[u] ?: self(self, u));
if (tin[v] == low) {
while (scc_id[v] < 0) scc_id[st[--s]] = num_sccs;
auto dfs = [&](auto&& self, int u) -> int {
int low = tin[u] = ++q;
st[s++] = u;
for (int v : adj[u])
if (scc_id[v] < 0)
low = min(low, tin[v] ?: self(self, v));
if (tin[u] == low) {
while (scc_id[u] < 0) scc_id[st[--s]] = num_sccs;
num_sccs++;
}
return low;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ vector<pii> extra_edges(const auto& adj, int num_sccs,
int n = sz(adj);
vector<vi> scc_adj(num_sccs);
vector<bool> zero_in(num_sccs, 1);
rep(i, 0, n) for (int u : adj[i]) {
if (scc_id[i] == scc_id[u]) continue;
scc_adj[scc_id[i]].push_back(scc_id[u]);
zero_in[scc_id[u]] = 0;
rep(i, 0, n) for (int v : adj[i]) {
if (scc_id[i] == scc_id[v]) continue;
scc_adj[scc_id[i]].push_back(scc_id[v]);
zero_in[scc_id[v]] = 0;
}
vector<bool> vis(num_sccs);
auto dfs = [&](auto&& self, int v) {
if (empty(scc_adj[v])) return v;
for (int u : scc_adj[v])
if (!vis[u]) {
vis[u] = 1;
int zero_out = self(self, u);
auto dfs = [&](auto&& self, int u) {
if (empty(scc_adj[u])) return u;
for (int v : scc_adj[u])
if (!vis[v]) {
vis[v] = 1;
int zero_out = self(self, v);
if (zero_out != -1) return zero_out;
}
return -1;
Expand All @@ -55,7 +55,7 @@ vector<pii> extra_edges(const auto& adj, int num_sccs,
in_unused.pop_back();
} else edges.emplace_back(i, num_sccs - 1);
}
for (int v : in_unused) edges.emplace_back(0, v);
for (int u : in_unused) edges.emplace_back(0, u);
vi to_node(num_sccs);
rep(i, 0, n) to_node[scc_id[i]] = i;
for (auto& [u, v] : edges)
Expand Down
16 changes: 8 additions & 8 deletions library/graphs/uncommon/bridges.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
auto bridges(const auto& adj, int m) {
int n = sz(adj), num_ccs = 0, q = 0, s = 0;
vi br_id(n, -1), is_br(m), tin(n), st(n);
auto dfs = [&](auto&& self, int v, int p) -> int {
int low = tin[v] = ++q;
st[s++] = v;
for (auto [u, e] : adj[v])
if (e != p && br_id[u] < 0)
low = min(low, tin[u] ?: self(self, u, e));
if (tin[v] == low) {
auto dfs = [&](auto&& self, int u, int p) -> int {
int low = tin[u] = ++q;
st[s++] = u;
for (auto [v, e] : adj[u])
if (e != p && br_id[v] < 0)
low = min(low, tin[v] ?: self(self, v, e));
if (tin[u] == low) {
if (p != -1) is_br[p] = 1;
while (br_id[v] < 0) br_id[st[--s]] = num_ccs;
while (br_id[u] < 0) br_id[st[--s]] = num_ccs;
num_ccs++;
}
return low;
Expand Down
16 changes: 8 additions & 8 deletions library/graphs/uncommon/cuts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@
auto cuts(const auto& adj, int m) {
int n = sz(adj), num_bccs = 0, q = 0, s = 0;
vi bcc_id(m, -1), is_cut(n), tin(n), st(m);
auto dfs = [&](auto&& self, int v, int p) -> int {
int low = tin[v] = ++q;
for (auto [u, e] : adj[v]) {
assert(v != u);
auto dfs = [&](auto&& self, int u, int p) -> int {
int low = tin[u] = ++q;
for (auto [v, e] : adj[u]) {
assert(u != v);
if (e == p) continue;
if (tin[u] < tin[v]) st[s++] = e;
if (tin[v] < tin[u]) st[s++] = e;
int lu = -1;
low = min(low, tin[u] ?: (lu = self(self, u, e)));
if (lu >= tin[v]) {
is_cut[v] = p >= 0 || tin[v] + 1 < tin[u];
low = min(low, tin[v] ?: (lu = self(self, v, e)));
if (lu >= tin[u]) {
is_cut[u] = p >= 0 || tin[u] + 1 < tin[v];
while (bcc_id[e] < 0) bcc_id[st[--s]] = num_bccs;
num_bccs++;
}
Expand Down
32 changes: 16 additions & 16 deletions library/trees/hld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! HLD<0> hld(adj);
//! hld.path(u, v, [&](int l, int r) { // [l, r)
//! });
//! auto [l, r] = hld.subtree(v); // [l, r)
//! auto [l, r] = hld.subtree(u); // [l, r)
//! @endcode
//! @time O(n + q log^2 n)
//! @space O(n)
Expand All @@ -15,23 +15,23 @@ template<bool VALS_EDGES> struct HLD {
vi p, siz, rt, tin;
HLD(auto& adj):
n(sz(adj)), p(n), siz(n, 1), rt(n), tin(n) {
auto dfs1 = [&](auto&& self, int v) -> void {
for (int& u : adj[v]) {
iter_swap(ranges::find(adj[u], v), rbegin(adj[u]));
adj[u].pop_back();
p[u] = v;
self(self, u);
siz[v] += siz[u];
if (siz[u] > siz[adj[v][0]]) swap(u, adj[v][0]);
auto dfs1 = [&](auto&& self, int u) -> void {
for (int& v : adj[u]) {
iter_swap(ranges::find(adj[v], u), rbegin(adj[v]));
adj[v].pop_back();
p[v] = u;
self(self, v);
siz[u] += siz[v];
if (siz[v] > siz[adj[u][0]]) swap(v, adj[u][0]);
}
};
dfs1(dfs1, 0);
int tim = 0;
auto dfs2 = [&](auto&& self, int v) -> void {
tin[v] = tim++;
for (int u : adj[v]) {
rt[u] = (u == adj[v][0] ? rt[v] : u);
self(self, u);
auto dfs2 = [&](auto&& self, int u) -> void {
tin[u] = tim++;
for (int v : adj[u]) {
rt[v] = (v == adj[u][0] ? rt[u] : v);
self(self, v);
}
};
dfs2(dfs2, 0);
Expand All @@ -44,7 +44,7 @@ template<bool VALS_EDGES> struct HLD {
}
f(tin[u] + VALS_EDGES, tin[v] + 1);
}
pii subtree(int v) {
return {tin[v] + VALS_EDGES, tin[v] + siz[v]};
pii subtree(int u) {
return {tin[u] + VALS_EDGES, tin[u] + siz[u]};
}
};
12 changes: 6 additions & 6 deletions library/trees/lca_rmq.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ struct LCA {
LCA(const auto& adj):
n(sz(adj)), tin(n), siz(n, 1), d(n), p(n) {
vi order;
auto dfs = [&](auto&& self, int v) -> void {
tin[v] = sz(order), order.push_back(v);
for (int u : adj[v])
if (u != p[v])
d[u] = d[p[u] = v] + 1, self(self, u),
siz[v] += siz[u];
auto dfs = [&](auto&& self, int u) -> void {
tin[u] = sz(order), order.push_back(u);
for (int v : adj[u])
if (v != p[u])
d[v] = d[p[v] = u] + 1, self(self, v),
siz[u] += siz[v];
};
dfs(dfs, 0);
rmq = {order,
Expand Down
32 changes: 16 additions & 16 deletions library/trees/linear_kth_par.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,28 @@ template<int KAPPA = 2> struct linear_kth_par {
jmp[t] = st[max(0, s - KAPPA * (t & -t))];
t++;
};
auto dfs = [&](auto&& self, int v, int p) -> void {
int& l = leaf[v] = st[d[v]] = v;
pos[v] = t;
calc(d[v]);
for (int u : adj[v])
if (u != p) {
d[u] = 1 + d[v];
self(self, u, v);
if (d[l] < d[leaf[u]]) l = leaf[u];
calc(d[v]);
auto dfs = [&](auto&& self, int u, int p) -> void {
int& l = leaf[u] = st[d[u]] = u;
pos[u] = t;
calc(d[u]);
for (int v : adj[u])
if (v != p) {
d[v] = 1 + d[u];
self(self, v, u);
if (d[l] < d[leaf[v]]) l = leaf[v];
calc(d[u]);
}
int s = (d[l] - d[v]) * (2 * KAPPA + 3) / KAPPA;
int s = (d[l] - d[u]) * (2 * KAPPA + 3) / KAPPA;
s = min(max(s, 2 * KAPPA), d[l] + 1);
rep(i, sz(lad[l]), s) lad[l].push_back(st[d[l] - i]);
};
dfs(dfs, 0, 0);
}
int kth_par(int v, int k) {
assert(0 <= k && k <= d[v]);
int anc_d = d[v] - k;
int kth_par(int u, int k) {
assert(0 <= k && k <= d[u]);
int anc_d = d[u] - k;
if (unsigned j = k / (KAPPA + 1); j)
j = bit_floor(j), v = jmp[(pos[v] & -j) | j];
return v = leaf[v], lad[v][d[v] - anc_d];
j = bit_floor(j), u = jmp[(pos[u] & -j) | j];
return u = leaf[u], lad[u][d[u] - anc_d];
}
};
20 changes: 10 additions & 10 deletions library/trees/linear_lca.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@ struct linear_lca {
linear_lca(const auto& adj):
n(sz(adj)), d(n), in(n), asc(n), head(n + 1) {
vector<pii> order;
auto dfs = [&](auto&& self, int v, int p) -> void {
order.emplace_back(v, p);
in[v] = sz(order);
for (int u : adj[v])
if (u != p) {
d[u] = 1 + d[v];
self(self, u, v);
head[in[u]] = v;
if (lsb(in[v]) < lsb(in[u])) in[v] = in[u];
auto dfs = [&](auto&& self, int u, int p) -> void {
order.emplace_back(u, p);
in[u] = sz(order);
for (int v : adj[u])
if (v != p) {
d[v] = 1 + d[u];
self(self, v, u);
head[in[v]] = u;
if (lsb(in[u]) < lsb(in[v])) in[u] = in[v];
}
};
dfs(dfs, 0, 0);
for (auto [v, p] : order) asc[v] = asc[p] | lsb(in[v]);
for (auto [u, p] : order) asc[u] = asc[p] | lsb(in[u]);
}
int lca(int u, int v) {
if (unsigned j = in[u] ^ in[v]; j) {
Expand Down
Loading
Loading