#ifndef HENZINGER_KING_H_ #define HENZINGER_KING_H_ #include "algorithm/dynamic_reachability.h" #include "algorithm/frigioni.h" using namespace graph; constexpr int threshold = 5; namespace algo { template class HenzingerKing : public DynamicReachability { public: HenzingerKing() = default; HenzingerKing(Digraph G) { this->G = G; } // Initialize decremental maintenance data structure and the empty set S void init() override; // Execute query q(u, v) from vertex u to vertex v by querying the // decremental reachability data structure at the start of the phase // and then if necessary check the set S bool query(const T& u, const T& v) override; // Remove collection of edges from the decremental maintenance data structure // and for every vertex in set S, rebuilt reachability trees from scratch void remove(const std::vector>& edges); // Insert collection of edges in set S, if threshold is reached re-initialize // algorithm, otherwise construct reachability trees for the vertex that is // the center-of-insertions void insert(const T& c, const std::vector& vertices); private: // Decremental maintenance data structure Frigioni frigioni; // Collection of vertices that have been centers of insertions in this phase std::set S; // Maintain in-out bfs trees std::unordered_map> In; std::unordered_map> Out; }; template void HenzingerKing::init() { S.clear(); frigioni = Frigioni(this->G); frigioni.init(); } template bool HenzingerKing::query(const T& u, const T& v) { if (frigioni.query(u, v)) return true; return std::any_of(S.begin(), S.end(), [&](const T& w) { return In[w].adjList.contains(u) && Out[w].adjList.contains(v); }); } template void HenzingerKing::remove(const std::vector>& edges) { for (const auto& [u, v] : edges) { this->G.remove(u, v); } frigioni.remove(edges); for (const auto& w : S) { In[w] = BreadthFirstTree(this->G.reverse(), w); Out[w] = BreadthFirstTree(this->G, w); } } template void HenzingerKing::insert(const T& c, const std::vector& vertices) { for (const auto& w : vertices) this->G.insert(c, w); S.insert(c); if (S.size() > threshold) { init(); return; } In[c] = BreadthFirstTree(this->G.reverse(), c); Out[c] = BreadthFirstTree(this->G, c); } } // namespace algo #endif