#ifndef TARJAN_H_ #define TARJAN_H_ #include "graph/scc.h" #include #include using namespace graph; namespace algo { template class Tarjan { public: Tarjan(Digraph G) : G(G) {} std::vector> execute(); 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; }; Digraph G; std::stack S; std::int16_t index = 0; std::map p; std::vector> SCCs; }; template void Tarjan::strongConnect(const T& v) { p[v].index = p[v].lowlink = index++; p[v].onStack = true; S.push(v); for (const auto& w : G.adjMatrix[v]) { if (p[w].index == -1) { strongConnect(w); p[v].lowlink = std::min(p[v].lowlink, p[w].lowlink); } else if (p[w].onStack) { p[v].lowlink = std::min(p[v].lowlink, p[w].index); } } // If v is a root node, pop the stack and generate an SCC if (p[v].lowlink == p[v].index) { //std::vector scc; std::map> scc; bool finished = false; do { const auto w = S.top(); S.pop(); p[w].onStack = false; scc[w] = G.adjMatrix[w]; finished = p[w].index == p[v].index; } while (!finished); SCCs.push_back(scc); } } template std::vector> Tarjan::execute() { for (auto& v : G.adjMatrix) { if (p[v.first].index == -1) { strongConnect(v.first); } } return SCCs; } } // namespace algo #endif