From e488b309c8701f3ed9bb14f652294fdad6e3b8f1 Mon Sep 17 00:00:00 2001 From: stefiosif Date: Mon, 27 Jun 2022 17:45:47 +0300 Subject: [PATCH] Update decremental maintenance of SCC algorithm --- algorithm/decremental_maintenance.h | 63 +++++++++++++++++++++-------- algorithm/roditty_zwick.h | 4 +- graph/scc.h | 2 + test/algorithm_test.cc | 3 +- 4 files changed, 53 insertions(+), 19 deletions(-) diff --git a/algorithm/decremental_maintenance.h b/algorithm/decremental_maintenance.h index ab54e59..a20ef2d 100644 --- a/algorithm/decremental_maintenance.h +++ b/algorithm/decremental_maintenance.h @@ -20,40 +20,71 @@ public: void init(); // - void query(); + bool query(const T& u, const T& v); // - void remove(); + void remove(const T& u, const T& v); private: Digraph G; + + // Array used to answer strong connectivity queries in O(1) time + std::map A; + + // Connect SCC/SCC representative with 2 SPTs + // pair.first: Shortest-paths out-tree + // pair.second: Shortest-paths in-tree + std::map, Digraph>> SPT; + + // Connect each representative with its SCC + std::map> SCCs; }; template void DecrementalMaintenance::init() { - std::map A; - Tarjan tarjan(G); + auto tarjan = Tarjan(G).run(); - auto sccs = tarjan.run(); + for (auto& C : tarjan) { + const auto& w = C.representative(); - for (auto& scc : sccs) { - const auto& root = scc.representative(); - BFS bfs(scc); - auto spt = bfs.run(root); - for (const auto& vertex : scc.vertices) { - A[vertex] = root; - } + // Create shortest-paths out-tree/in-tree + auto outTree = BFS(C).run(w); + SPT[w] = std::make_pair(outTree, outTree.reverse()); + // Update A with current SCCs vertices + for (const auto& v : C.vertices) + A[v] = w; + + // Link SCC with its representative w + SCCs[w] = C; } } template -inline void DecrementalMaintenance::query() -{ +bool DecrementalMaintenance::query(const T& u, const T& v) { + return A[u] == A[v]; } template -inline void DecrementalMaintenance::remove() -{ +void DecrementalMaintenance::remove(const T& u, const T& v) { + // If u and v are not in the same SCC, do nothing + if (A[u] != A[v]) return; + + const auto& w = A[u]; + + // If edge e(u, v) is not contained in In(w) and Out(w), do nothing + if (!SPT[w].first.vertices.contains(w) && + !SPT[w].second.vertices.contains(w)) + return; + + // Update In(w) and Out(w) + auto inTree = BFS(SCCs[w]).run(w); + SPT[w] = std::make_pair(inTree, inTree.reverse()); + + if (!SPT[w].second.vertices.contains(u) || + !SPT[w].first.vertices.contains(v)) { + // TODO: Decompose C into C1, C2, ... Ck + } + } }; // namespace algo diff --git a/algorithm/roditty_zwick.h b/algorithm/roditty_zwick.h index 1ee077d..5386fdd 100644 --- a/algorithm/roditty_zwick.h +++ b/algorithm/roditty_zwick.h @@ -14,10 +14,10 @@ public: virtual void init() =0; // - virtual void query() =0; + virtual bool query(const T& u, const T& v) =0; // - virtual void remove() =0; + virtual void remove(const T& u, const T& v) =0; }; template diff --git a/graph/scc.h b/graph/scc.h index 21b175d..b7139b8 100644 --- a/graph/scc.h +++ b/graph/scc.h @@ -10,6 +10,8 @@ namespace graph { template class SCC : public Graph { public: + SCC() = default; + SCC(std::map> scc); // diff --git a/test/algorithm_test.cc b/test/algorithm_test.cc index 9782bd5..ab465df 100644 --- a/test/algorithm_test.cc +++ b/test/algorithm_test.cc @@ -4,7 +4,6 @@ #include "graph/scc.h" #include "algorithm/tarjan.h" #include "algorithm/bfs.h" -#include "algorithm/roditty_zwick.h" #include "algorithm/decremental_maintenance.h" using namespace graph; @@ -133,5 +132,7 @@ TEST_SUITE("Algorithm") { algo::DecrementalMaintenance rz(G); rz.init(); + + //CHECK_EQ(rz.query(1, 2), true); } } \ No newline at end of file