From 31567f9e572a2b8c15590f237f3907a870784a16 Mon Sep 17 00:00:00 2001 From: stefiosif Date: Wed, 20 Jul 2022 23:04:06 +0300 Subject: [PATCH] Add BreadthFirstTree's to decremental maintenance algorithm and delete In/Out tree classes --- algorithm/decremental_scc.h | 44 +++++++++++++++++-------------------- tree/breadth_first_tree.h | 8 +++---- tree/in_tree.h | 20 ----------------- tree/out_tree.h | 20 ----------------- 4 files changed, 24 insertions(+), 68 deletions(-) delete mode 100644 tree/in_tree.h delete mode 100644 tree/out_tree.h diff --git a/algorithm/decremental_scc.h b/algorithm/decremental_scc.h index a3e7a01..c8674ca 100644 --- a/algorithm/decremental_scc.h +++ b/algorithm/decremental_scc.h @@ -7,6 +7,7 @@ #include "tree/breadth_first_tree.h" using namespace graph; +using namespace tree; namespace algo { @@ -28,10 +29,9 @@ private: // 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; + // Maintain in-out bfs trees + std::map> inTree; + std::map> outTree; // Connect each representative with its SCC std::map> connection; @@ -49,15 +49,14 @@ void DecrementalSCC::findSCC() { for (auto& C : SCCs) { const auto& w = C.representative(); - // Create shortest-paths out-tree/in-tree - auto outTree = Digraph(BreadthFirstSearch(C).execute(w)); - SPT[w] = std::make_pair(outTree, outTree.reverse()); - - // Update A with current SCCs vertices for (const auto& v : C.vertices) A[v] = w; + + outTree[w] = + BreadthFirstTree(BreadthFirstSearch(C).execute(w)); + inTree[w] = + BreadthFirstTree(BreadthFirstSearch(C.reverse()).execute(w)); - // Link SCC with its representative w connection[w] = C; } } @@ -69,30 +68,27 @@ bool DecrementalSCC::query(const T& u, const T& v) { template void DecrementalSCC::remove(const T& u, const T& v) { + G.adjMatrix[u].erase(v); + // If u and v are not in the same SCC, do nothing if (A[u] != A[v]) return; const auto& w = A[u]; + connection[w].remove(u, v); - // 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)){ - connection[w].adjMatrix[u].erase(v); - G.adjMatrix[u].erase(v); - return; + // Update In(w) and Out(w) if they contain the edge + if (inTree[w].contains(u, v) || outTree[w].contains(u, v)) { + auto C = connection[w]; + inTree[w] = + BreadthFirstTree(BreadthFirstSearch(C.reverse()).execute(w)); + outTree[w] = + BreadthFirstTree(BreadthFirstSearch(C).execute(w)); } - // Update In(w) and Out(w) - connection[w].adjMatrix[u].erase(v); - G.adjMatrix[u].erase(v); - auto inTree = Digraph(BreadthFirstSearch(connection[w]).execute(w)); - SPT[w] = std::make_pair(inTree, inTree.reverse()); // If a SCC is broken, compute all SCCs again - if (!SPT[w].second.vertices.contains(u) || - !SPT[w].first.vertices.contains(v)) { + if (!inTree[w].contains(u) || !outTree[w].contains(v)) { findSCC(); } - } }; // namespace algo diff --git a/tree/breadth_first_tree.h b/tree/breadth_first_tree.h index 04c4352..0a3beeb 100644 --- a/tree/breadth_first_tree.h +++ b/tree/breadth_first_tree.h @@ -1,27 +1,27 @@ #ifndef BREADTH_FIRST_TREE_H_ #define BREADTH_FIRST_TREE_H_ -#include "out_tree.h" +#include "directed_rooted_tree.h" #include "algorithm/breadth_first_search.h" using namespace graph; namespace tree { template -class BreadthFirstTree : public OutTree { +class BreadthFirstTree : public DirectedRootedTree { public: BreadthFirstTree() = default; BreadthFirstTree(Digraph G, T root); BreadthFirstTree(std::map> G) - : OutTree::OutTree(G) {} + : DirectedRootedTree::DirectedRootedTree(G) {} }; template BreadthFirstTree::BreadthFirstTree(Digraph G, T root) { auto bfs = algo::BreadthFirstSearch(G).execute(root); - Graph::adjMatrix = bfs; + this->adjMatrix = bfs; } } // namespace tree diff --git a/tree/in_tree.h b/tree/in_tree.h deleted file mode 100644 index 2470692..0000000 --- a/tree/in_tree.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef IN_TREE_H_ -#define IN_TREE_H_ - -#include "directed_rooted_tree.h" -using namespace graph; - -namespace tree { - -template -class InTree : public DirectedRootedTree { -public: - InTree() = default; - - InTree(std::map> G) - : DirectedRootedTree::DirectedRootedTree(G) {} -}; - -} // namespace tree - -#endif \ No newline at end of file diff --git a/tree/out_tree.h b/tree/out_tree.h deleted file mode 100644 index 9e0cda7..0000000 --- a/tree/out_tree.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef OUT_TREE_H_ -#define OUT_TREE_H_ - -#include "directed_rooted_tree.h" -using namespace graph; - -namespace tree { - -template -class OutTree : public DirectedRootedTree { -public: - OutTree() = default; - - OutTree(std::map> G) - : DirectedRootedTree::DirectedRootedTree(G) {} -}; - -} // namespace tree - -#endif \ No newline at end of file