#ifndef FRIGIONI_H_ #define FRIGIONI_H_ #include "algorithm/decremental_reachability.h" #include "algorithm/roditty_zwick.h" #include using namespace graph; namespace algo { template class Frigioni : public DecrementalReachability { public: Frigioni() = default; Frigioni(Digraph G) { this->G = G; } // void init() override; // bool query(const T& u, const T& v) override; // void remove(const T& u, const T& v) override; private: // Transitive closure matrix, used to answer reachability queries in O(1) std::map> TC; // Connect each vertex with its representative SCC std::map> C; // Each scc's representative vertex reachability tree std::map> RT; // Incoming / Outgoing / Internal edges of each SCC // Maps each SCC representative with struct Edges struct Edges { std::set> in; std::set> inc; std::set> out; }; std::map E; // Decremental maintenance of strongly connected components RodittyZwick decremental; }; template void Frigioni::init() { auto SCCs = Tarjan(this->G.adjMatrix).execute(); decremental = RodittyZwick(this->G); decremental.init(); for (auto& scc : SCCs) { RT[scc.id] = BreadthFirstTree(this->G, scc.id); for (const auto& u : this->G.vertices()) { for (const auto& v : this->G.adjMatrix[u]) { TC[u][v] = false; if (scc.member(u)) { if (scc.member(v)) E[scc.id].in.insert(std::make_pair(u, v)); else E[scc.id].out.insert(std::make_pair(u, v)); } else if (scc.member(v)) { E[scc.id].inc.insert(std::make_pair(u, v)); } } } } for (auto& scc : SCCs) { for (const auto& u : this->G.vertices()) { if (scc.member(u)) { for (const auto& v : RT[scc.id].vertices()) { TC[u][v] = true; } } } } } template bool Frigioni::query(const T& u, const T& v) { return TC[u][v]; } template void Frigioni::remove(const T& u, const T& v) { } } // namespace algo #endif