11#ifndef WEILYCODER_TARJAN_HPP
22#define WEILYCODER_TARJAN_HPP
33
4+ /* *
5+ * @file tarjan.hpp
6+ * @brief Tarjan's Algorithm for Graph Connected Problems
7+ */
8+
49#include < algorithm>
510#include < cstddef>
611#include < stack>
712#include < utility>
813#include < vector>
914
1015namespace weilycoder {
16+ /* *
17+ * @brief Strongly Connected Components using Tarjan's Algorithm
18+ * @tparam ptr_t Type for representing indices (default: size_t)
19+ */
1120template <typename ptr_t = size_t > struct StrongConnectedComponents {
1221 ptr_t dfs_time = 0 ;
1322
@@ -18,11 +27,24 @@ template <typename ptr_t = size_t> struct StrongConnectedComponents {
1827
1928 std::vector<std::vector<ptr_t >> sccs;
2029
30+ /* *
31+ * @brief Constructs a StrongConnectedComponents for n nodes
32+ * @param n Number of nodes
33+ */
2134 StrongConnectedComponents (ptr_t n)
2235 : in_stack(n, false ), dfn(n, 0 ), low(n, 0 ), graph(n) {}
2336
37+ /* *
38+ * @brief Adds a directed edge from u to v
39+ * @param u Source node
40+ * @param v Destination node
41+ */
2442 void add_edge (ptr_t u, ptr_t v) { graph[u].push_back (v); }
2543
44+ /* *
45+ * @brief Tarjan's DFS to find SCCs
46+ * @param u Current node
47+ */
2648 void tarjan (ptr_t u) {
2749 dfn[u] = low[u] = ++dfs_time;
2850 stk.push (u), in_stack[u] = true ;
@@ -45,6 +67,10 @@ template <typename ptr_t = size_t> struct StrongConnectedComponents {
4567 }
4668 }
4769
70+ /* *
71+ * @brief Solves for all SCCs in the graph, sorting them in DFS order,
72+ * i.e., if there is an edge from SCC A to SCC B, then A appears before B
73+ */
4874 void solve () {
4975 for (size_t i = 0 ; i < graph.size (); ++i)
5076 if (!dfn[i])
@@ -53,6 +79,10 @@ template <typename ptr_t = size_t> struct StrongConnectedComponents {
5379 }
5480};
5581
82+ /* *
83+ * @brief Two-Edge Connected Components using Tarjan's Algorithm
84+ * @tparam ptr_t Type for representing indices (default: size_t)
85+ */
5686template <typename ptr_t = size_t > struct TwoEdgeConnectedComponents {
5787 ptr_t dfs_time = 0 , edge_time = 1 ;
5888
@@ -63,15 +93,29 @@ template <typename ptr_t = size_t> struct TwoEdgeConnectedComponents {
6393
6494 std::vector<std::vector<ptr_t >> eccs;
6595
96+ /* *
97+ * @brief Constructs a TwoEdgeConnectedComponents for n nodes
98+ * @param n Number of nodes
99+ */
66100 TwoEdgeConnectedComponents (ptr_t n)
67101 : in_stack(n, false ), dfn(n, 0 ), low(n, 0 ), graph(n) {}
68102
103+ /* *
104+ * @brief Adds an undirected edge between u and v
105+ * @param u One endpoint
106+ * @param v Other endpoint
107+ */
69108 void add_edge (ptr_t u, ptr_t v) {
70109 graph[u].emplace_back (v, edge_time);
71110 graph[v].emplace_back (u, edge_time);
72111 edge_time++;
73112 }
74113
114+ /* *
115+ * @brief Tarjan's DFS to find 2-edge connected components
116+ * @param u Current node
117+ * @param parent_edge Edge ID of the edge leading to u
118+ */
75119 void tarjan (ptr_t u, ptr_t parent_edge) {
76120 dfn[u] = low[u] = ++dfs_time;
77121 stk.push (u), in_stack[u] = true ;
@@ -96,13 +140,20 @@ template <typename ptr_t = size_t> struct TwoEdgeConnectedComponents {
96140 }
97141 }
98142
143+ /* *
144+ * @brief Solves for all 2-edge connected components in the graph
145+ */
99146 void solve () {
100147 for (size_t i = 0 ; i < graph.size (); ++i)
101148 if (!dfn[i])
102149 tarjan (i, 0 );
103150 }
104151};
105152
153+ /* *
154+ * @brief Biconnected Components using Tarjan's Algorithm
155+ * @tparam ptr_t Type for representing indices (default: size_t)
156+ */
106157template <typename ptr_t = size_t > struct BiconnectedComponents {
107158 ptr_t dfs_time = 0 ;
108159
@@ -113,14 +164,28 @@ template <typename ptr_t = size_t> struct BiconnectedComponents {
113164 std::vector<bool > is_cut;
114165 std::vector<std::vector<ptr_t >> dccs;
115166
167+ /* *
168+ * @brief Constructs a BiconnectedComponents for n nodes
169+ * @param n Number of nodes
170+ */
116171 BiconnectedComponents (ptr_t n)
117172 : dfn(n, 0 ), low(n, 0 ), graph(n), is_cut(n, false ) {}
118173
174+ /* *
175+ * @brief Adds an undirected edge between u and v
176+ * @param u One endpoint
177+ * @param v Other endpoint
178+ */
119179 void add_edge (ptr_t u, ptr_t v) {
120180 graph[u].push_back (v);
121181 graph[v].push_back (u);
122182 }
123183
184+ /* *
185+ * @brief Tarjan's DFS to find biconnected components
186+ * @param u Current node
187+ * @param is_root Whether u is the root of the DFS tree
188+ */
124189 void tarjan (ptr_t u, bool is_root) {
125190 dfn[u] = low[u] = ++dfs_time, stk.push (u);
126191
@@ -148,6 +213,9 @@ template <typename ptr_t = size_t> struct BiconnectedComponents {
148213 }
149214 }
150215
216+ /* *
217+ * @brief Solves for all biconnected components in the graph
218+ */
151219 void solve () {
152220 for (size_t i = 0 ; i < graph.size (); ++i)
153221 if (!dfn[i])
0 commit comments