#ifndef TARJAN_H_ #define TARJAN_H_ #include "graph/scc.h" #include #include #include namespace algo { template class Tarjan { public: Tarjan() = default; explicit Tarjan(std::unordered_map> adjList) : adjList(adjList) {} // auto execute(); // void strongConnect(const T& u); private: std::unordered_map> adjList; std::stack S; std::int16_t index = 0; std::vector> SCCs; T cid{}; struct Vertex { int index = -1; int lowlink = -1; bool onStack = false; }; std::unordered_map V; }; template void Tarjan::strongConnect(const T& u) { V[u].index = V[u].lowlink = index++; S.push(u); V[u].onStack = true; for (const auto& w : adjList[u]) { if (V[w].index == -1) { strongConnect(w); V[u].lowlink = std::min(V[u].lowlink, V[w].lowlink); } else if (V[w].onStack) { V[u].lowlink = std::min(V[u].lowlink, V[w].index); } } // If u is a root node, pop the stack and generate an SCC if (V[u].lowlink == V[u].index) { std::unordered_map> scc; bool finished = false; cid = S.top(); do { const auto w = S.top(); S.pop(); V[w].onStack = false; scc[w] = adjList[w]; finished = (w == u); } while (!finished); SCCs.push_back({ scc, static_cast(cid) }); } } template auto Tarjan::execute() { for (const auto& u : std::views::keys(adjList)) { if (V[u].index == -1) strongConnect(u); } return SCCs; } } // namespace algo #endif