diff --git a/src/code/graph/v_bcc.hpp b/src/code/graph/v_bcc.hpp index bd5d47004..81cb349b2 100644 --- a/src/code/graph/v_bcc.hpp +++ b/src/code/graph/v_bcc.hpp @@ -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 v_bcc { - vvec CR g; - - public: - u32 id; +template +struct v_bcc { vecu dfn, low; - vecb cut; vvecu belongs; + vecb cut; - //! EW need rev_edge - CEXPE v_bcc(cT_(vvec) 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 + CEXP v_bcc(alist 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); } }; diff --git a/src/test_cpverifier/aizu-grl/grl_3_a.test.cpp b/src/test_cpverifier/aizu-grl/grl_3_a.test.cpp new file mode 100644 index 000000000..bdbe18d25 --- /dev/null +++ b/src/test_cpverifier/aizu-grl/grl_3_a.test.cpp @@ -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 bcc(g); + flt_ (u32, i, 0, n) + if (bcc.cut[i]) std::cout << i << '\n'; + return 0; +} diff --git a/src/test_cpverifier/library-checker-graph/biconnected_components.test.cpp b/src/test_cpverifier/library-checker-graph/biconnected_components.test.cpp index cf8613202..84f8873a1 100644 --- a/src/test_cpverifier/library-checker-graph/biconnected_components.test.cpp +++ b/src/test_cpverifier/library-checker-graph/biconnected_components.test.cpp @@ -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 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 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 << ' '; diff --git a/src/test_tinplate/graph/v_bcc.cpp b/src/test_tinplate/graph/v_bcc.cpp index 30d452f11..deee3ee6b 100644 --- a/src/test_tinplate/graph/v_bcc.cpp +++ b/src/test_tinplate/graph/v_bcc.cpp @@ -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 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 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'; } }