Skip to content

Commit

Permalink
refactor: better v_bcc
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiphereth-A committed Feb 27, 2025
1 parent f005a08 commit 4669c0d
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 56 deletions.
66 changes: 33 additions & 33 deletions src/code/graph/v_bcc.hpp
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
#ifndef TIFALIBS_GRAPH_V_BCC
#define TIFALIBS_GRAPH_V_BCC

#include "../util/util.hpp"
#include "alist.hpp"

namespace tifa_libs::graph {

template <class EW>
class v_bcc {
vvec<EW> CR g;

public:
u32 id;
template <bool get_cut = false, bool get_belongs = true>
struct v_bcc {
vecu dfn, low;
vecb cut;
vvecu belongs;
vecb cut;

//! EW need rev_edge
CEXPE v_bcc(cT_(vvec<EW>) G) NE : g(G) { build(); }

CEXP void build() NE {
u32 cnt = 0, n = u32(g.size());
id = 0, dfn = low = vecu(n, n), cut = vecb(n, 0);
vecu s;
auto dfs = [&](auto &&dfs, u32 u, u32 fa, u32 inv_from) NE -> void {
dfn[u] = low[u] = cnt++;
if (u == fa && g[u].size() == 0) cut[u] = 1, belongs.push_back(vecu(1, u)), ++id;
s.push_back(u);
flt_ (u32, i, 0, (u32)g[u].size()) {
auto v = g[u][i];
if (v.to == fa && i == inv_from) continue;
if (dfn[v.to] == n) {
if (dfs(dfs, v.to, u, v.inv), low[u] = min(low[u], low[v.to]); low[v.to] >= dfn[u]) {
u32 p;
cut[u] = 1, belongs.push_back(vecu(1, u));
do p = s.back(), s.pop_back(), belongs[id].push_back(p);
while (p != v.to);
++id;
//! G should be undirect
template <bool with_deg>
CEXP v_bcc(alist<with_deg> CR g) NE : dfn(g.size()), low(g.size()) {
if CEXP (get_cut) cut = vecb(g.size());
vecu stk;
u32 cnt = 0, start;
auto tarjan = [&](auto&& f, u32 u, u32 fa) -> void {
u32 son = 0;
low[u] = dfn[u] = ++cnt;
if CEXP (get_belongs) stk.push_back(u);
for (auto v : g[u])
if (!dfn[v]) {
++son, f(f, v, u), low[u] = min(low[u], low[v]);
if (low[v] >= dfn[u]) {
if CEXP (get_cut)
if (u != start) cut[u] = true;
if CEXP (get_belongs) {
vecu now;
now.reserve(stk.size() + 1);
while (!stk.empty() && (now.empty() || now.back() != v)) now.push_back(stk.back()), stk.pop_back();
now.push_back(u), now.shrink_to_fit(), belongs.push_back(now);
}
}
} else low[u] = min(low[u], dfn[v.to]);
}
} else if (v != fa) low[u] = min(low[u], dfn[v]);
if CEXP (get_cut)
if (u == start && son >= 2) cut[u] = true;
if CEXP (get_belongs)
if (!~fa && !son) belongs.push_back({u});
};
flt_ (u32, i, 0, n)
if (dfn[i] == n) dfs(dfs, i, i, -1_u32);
flt_ (u32, i, 0, g.size())
if (!dfn[i]) tarjan(tarjan, start = i, -1_u32);
}
};

Expand Down
18 changes: 18 additions & 0 deletions src/test_cpverifier/aizu-grl/grl_3_a.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/all/GRL_3_A"

#include "../../code/graph/v_bcc.hpp"

int main() {
std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
u32 n, m;
std::cin >> n >> m;
tifa_libs::graph::alist g(n);
for (u32 i = 0, u, v; i < m; ++i) {
std::cin >> u >> v;
g.add_arc(u, v), g.add_arc(v, u);
}
tifa_libs::graph::v_bcc<true, false> bcc(g);
flt_ (u32, i, 0, n)
if (bcc.cut[i]) std::cout << i << '\n';
return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,14 @@ int main() {
std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
u32 n, m;
std::cin >> n >> m;
struct EW {
u32 to, inv;
};
vvec<EW> e(n);
tifa_libs::graph::alist g(n);
for (u32 i = 0, u, v; i < m; ++i) {
std::cin >> u >> v;
if (u == v) continue;
u32 tem1 = u32(e[u].size()), tem2 = u32(e[v].size());
e[u].push_back({v, tem2});
e[v].push_back({u, tem1});
g.add_arc(u, v), g.add_arc(v, u);
}
tifa_libs::graph::v_bcc<EW> bcc(e);
std::cout << bcc.id << '\n';
for (u32 i = 0; i < bcc.id; ++i) {
tifa_libs::graph::v_bcc bcc(g);
std::cout << bcc.belongs.size() << '\n';
for (u32 i = 0; i < bcc.belongs.size(); ++i) {
std::cout << bcc.belongs[i].size() << ' ';
for (auto x : bcc.belongs[i])
std::cout << x << ' ';
Expand Down
20 changes: 8 additions & 12 deletions src/test_tinplate/graph/v_bcc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,17 @@ int main() {
std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
u32 n, m;
std::cin >> n >> m;
struct EW {
u32 to, inv;
};
vvec<EW> e(n);
tifa_libs::graph::alist g(n);
for (u32 i = 0, u, v; i < m; ++i) {
std::cin >> u >> v;
if (--u, --v; u == v) continue;
u32 tem1 = u32(e[u].size()), tem2 = u32(e[v].size());
e[u].push_back({v, tem2}), e[v].push_back({u, tem1});
--u, --v;
g.add_arc(u, v), g.add_arc(v, u);
}
tifa_libs::graph::v_bcc<EW> bcc(e);
std::cout << bcc.id << '\n';
flt_ (u32, i, 0, bcc.id) {
std::cout << bcc.belongs[i].size() << ' ';
for (auto x : bcc.belongs[i]) std::cout << x + 1 << ' ';
tifa_libs::graph::v_bcc bcc(g);
std::cout << bcc.belongs.size() << '\n';
flt_ (u32, i, 0, (u32)bcc.belongs.size()) {
std::cout << bcc.belongs[i].size();
for (auto x : bcc.belongs[i]) std::cout << ' ' << x + 1;
std::cout << '\n';
}
}
Expand Down

0 comments on commit 4669c0d

Please sign in to comment.