#ifndef TARJAN_H_ #define TARJAN_H_ #include "graph/graph.h" using namespace graph; #include #include #include #include namespace algo { template class Tarjan { public: Tarjan(Graph G) : G(G) {} // std::vector> run(); // void strongConnect(const T& v); private: // Necessary info about vertices when running Tarjan's algorithm struct Payload { std::int16_t index = -1; std::int16_t lowlink = -1; bool onStack = false; }; Graph G; std::stack S; std::int16_t index = 0; std::map vp; std::vector> SCCs; }; template void Tarjan::strongConnect(const T& v) { vp[v].index = vp[v].lowlink = index++; vp[v].onStack = true; S.push(v); for (const auto& w : G.adjMatrix[v]) { if (vp[w].index == -1) { strongConnect(w); vp[v].lowlink = std::min(vp[v].lowlink, vp[w].lowlink); } else if (vp[w].onStack) { vp[v].lowlink = std::min(vp[v].lowlink, vp[w].index); } } // If v is a root node, pop the stack and generate an SCC if (vp[v].lowlink == vp[v].index) { std::vector SCC; bool finished = false; do { const auto w = S.top(); S.pop(); vp[w].onStack = false; SCC.push_back(w); finished = vp[w].index == vp[v].index; } while (!finished); SCCs.push_back(SCC); } } template std::vector> Tarjan::run() { for (const auto& v : G.vertices) { if (vp[v].index == -1) { strongConnect(v); } } return SCCs; } } // namespace algo #endif