diff --git a/algorithm/decremental_scc.h b/algorithm/roditty_zwick.h similarity index 54% rename from algorithm/decremental_scc.h rename to algorithm/roditty_zwick.h index 37de51e..ad3a04c 100644 --- a/algorithm/decremental_scc.h +++ b/algorithm/roditty_zwick.h @@ -1,7 +1,7 @@ -#ifndef DECREMENTAL_SCC_H_ -#define DECREMENTAL_SCC_H_ +#ifndef RODITTY_ZWICK_H_ +#define RODITTY_ZWICK_H_ -#include "algorithm/roditty_zwick.h" +#include "algorithm/decremental_reachability.h" #include "algorithm/tarjan.h" #include "graph/breadth_first_tree.h" @@ -10,69 +10,69 @@ using namespace graph; namespace algo { template -class DecrementalSCC : public RodittyZwick { +class RodittyZwick : public DecrementalReachability { public: - DecrementalSCC() = default; + RodittyZwick() = default; - DecrementalSCC(Digraph G) : G(G) {} + RodittyZwick(Digraph G) { this->G = G; } - void init(); + // + void init() override; + // void findSCC(); // Return true if u and v are in the same SCC - bool query(const T& u, const T& v); + bool query(const T& u, const T& v) override; // Remove edge (u,v) and update A accordingly for fast checking query - void remove(const T& u, const T& v); + void remove(const T& u, const T& v) override; void setGraph(Digraph G); private: - Digraph G; - // Array used to answer strong connectivity queries in O(1) time std::map A; + // Connect each representative with its SCC + std::map> C; + // Maintain in-out bfs trees std::map> inTree; std::map> outTree; - - // Connect each representative with its SCC - std::map> SCC; }; template -void DecrementalSCC::init() { +void RodittyZwick::init() { findSCC(); } template -void DecrementalSCC::findSCC() { - auto SCCs = Tarjan(G.adjMatrix).execute(); +void RodittyZwick::findSCC() { + auto SCCs = Tarjan(this->G.adjMatrix).execute(); - for (auto& C : SCCs) { - const auto& w = C.id; + for (auto& SCC : SCCs) { + const auto& w = SCC.id; - for (const auto& v : std::views::keys(C.adjMatrix)) + for (const auto& v : std::views::keys(SCC.adjMatrix)) A[v] = w; - outTree[w] = BreadthFirstTree(C, w); - inTree[w] = BreadthFirstTree(C.reverse(), w); + outTree[w] = BreadthFirstTree(SCC, w); + inTree[w] = BreadthFirstTree(SCC.reverse(), w); - SCC[w] = C; + C[w] = SCC; } } template -bool DecrementalSCC::query(const T& u, const T& v) { +bool RodittyZwick::query(const T& u, const T& v) { return A[u] == A[v]; } template -void DecrementalSCC::remove(const T& u, const T& v) { +void RodittyZwick::remove(const T& u, const T& v) { const auto& w = A[u]; - SCC[w].remove(u, v); - G.remove(u, v); + C[w].remove(u, v); + this->G.remove(u, v); // If u and v are not in the same SCC, do nothing if (A[u] != A[v]) return; @@ -83,8 +83,8 @@ void DecrementalSCC::remove(const T& u, const T& v) { return; // Update In(w) and Out(w) - outTree[w] = BreadthFirstTree(SCC[w], w); - inTree[w] = BreadthFirstTree(SCC[w].reverse(), w); + outTree[w] = BreadthFirstTree(C[w], w); + inTree[w] = BreadthFirstTree(C[w].reverse(), w); // If a SCC is broken, compute all SCCs again if (!inTree[w].adjMatrix.count(u) || !outTree[w].adjMatrix.count(v)) @@ -92,7 +92,7 @@ void DecrementalSCC::remove(const T& u, const T& v) { } template -void DecrementalSCC::setGraph(Digraph G) { +void RodittyZwick::setGraph(Digraph G) { this->G = G; } diff --git a/test/decremental_reachability_test.cc b/test/decremental_reachability_test.cc index 8926180..658d561 100644 --- a/test/decremental_reachability_test.cc +++ b/test/decremental_reachability_test.cc @@ -1,6 +1,6 @@ #include -#include "algorithm/decremental_scc.h" +#include "algorithm/roditty_zwick.h" #include "algorithm/frigioni.h" #include "algorithm/italiano.h" @@ -8,7 +8,7 @@ using namespace graph; TEST_SUITE("Decremental Reachability Test") { - TEST_CASE("DecrementalSCC") { + TEST_CASE("RodittyZwick") { // 1 --> 2 --> 3 --> 1 // 3 --> 4 --> 5 --> 3 // 2 --> 6 --> 7 --> 8 --> 6 @@ -37,30 +37,30 @@ TEST_SUITE("Decremental Reachability Test") { REQUIRE_EQ(G.adjMatrix.size(), 13); - algo::DecrementalSCC decremental(G); - decremental.init(); + algo::RodittyZwick rodittyZwick(G); + rodittyZwick.init(); - SUBCASE("DecrementalSCC::query") { - CHECK_EQ(decremental.query(1, 5), true); - CHECK_EQ(decremental.query(1, 7), false); - CHECK_EQ(decremental.query(1, 9), false); + SUBCASE("RodittyZwick::query") { + CHECK_EQ(rodittyZwick.query(1, 5), true); + CHECK_EQ(rodittyZwick.query(1, 7), false); + CHECK_EQ(rodittyZwick.query(1, 9), false); } - SUBCASE("DecrementalSCC::remove") { - decremental.remove(12, 10); + SUBCASE("RodittyZwick::remove") { + rodittyZwick.remove(12, 10); - CHECK_EQ(decremental.query(12, 10), true); - CHECK_EQ(decremental.query(11, 10), true); + CHECK_EQ(rodittyZwick.query(12, 10), true); + CHECK_EQ(rodittyZwick.query(11, 10), true); - decremental.remove(9, 10); + rodittyZwick.remove(9, 10); - CHECK_EQ(decremental.query(12, 13), false); - CHECK_EQ(decremental.query(10, 12), false); + CHECK_EQ(rodittyZwick.query(12, 13), false); + CHECK_EQ(rodittyZwick.query(10, 12), false); - decremental.remove(2, 6); + rodittyZwick.remove(2, 6); - CHECK_EQ(decremental.query(5, 8), false); - CHECK_EQ(decremental.query(6, 8), true); + CHECK_EQ(rodittyZwick.query(5, 8), false); + CHECK_EQ(rodittyZwick.query(6, 8), true); } }