#ifndef TARJAN_H_ #define TARJAN_H_ #include "graph/graph.h" using namespace graph; #include #include #include #include #include namespace algorithm { template class Tarjan { public: Tarjan(Graph G) : G(G) {} void findSCC(); void strongConnect(Vertex& v); std::uint16_t index = 0; std::stack> S; private: Graph G; }; template void Tarjan::strongConnect(Vertex& v) { v.index, v.lowlink = index++; v.onStack = true; S.push(v); for (auto& w : v.edges) { if (w.index == -1) { // successor w has not yet been visited, recurse on it strongConnect(w); v.lowlink = std::min(v.lowlink, w.lowlink); } else if (w.onStack) { // successor w is in stack S and hence in the current SCC // if w is not on stack, then (v, w) is an edge pointing to an SCC // already found and must be ignored v.lowlink = std::min(v.lowlink, w.index); } } // if v is a root node, pop the stack and generate an SCC if (v.lowlink = v.index) { // start a new SCC Vertex w; do { w = S.top(); S.pop(); // add w to current SCC } while (w != v); } } template void Tarjan::findSCC() { for (auto& vertex : G.vertices) { if (vertex.index == -1) { strongConnect(vertex); } } } } // namespace algorithm #endif