42 #ifndef UTIL_GRAPH_STRONGLY_CONNECTED_COMPONENTS_H_
43 #define UTIL_GRAPH_STRONGLY_CONNECTED_COMPONENTS_H_
48 #include "ortools/base/logging.h"
49 #include "ortools/base/macros.h"
71 template <
typename NodeIndex,
typename Graph,
typename SccOutput>
73 const Graph& graph, SccOutput* components);
82 template <
typename NodeIndex>
104 template <
typename NodeIndex,
typename Graph,
typename SccOutput>
109 SccOutput* components) {
112 scc_start_index_.clear();
113 node_index_.assign(num_nodes, 0);
114 node_to_process_.clear();
122 for (
NodeIndex base_node = 0; base_node < num_nodes; ++base_node) {
123 if (node_index_[base_node] != 0)
continue;
124 DCHECK_EQ(0, node_to_process_.size());
125 node_to_process_.push_back(base_node);
127 const NodeIndex node = node_to_process_.back();
128 const NodeIndex index = node_index_[node];
131 scc_stack_.push_back(node);
132 current_scc_start = scc_stack_.size();
133 node_index_[node] = current_scc_start;
134 scc_start_index_.push_back(current_scc_start);
137 NodeIndex min_head_index = kSettledIndex;
138 for (
const NodeIndex head : graph[node]) {
139 const NodeIndex head_index = node_index_[head];
140 if (head_index == 0) {
141 node_to_process_.push_back(head);
144 min_head_index = std::min(min_head_index, head_index);
152 while (current_scc_start > min_head_index) {
153 scc_start_index_.pop_back();
154 current_scc_start = scc_start_index_.back();
157 node_to_process_.pop_back();
158 if (current_scc_start == index) {
160 components->emplace_back(&scc_stack_[current_scc_start - 1],
161 &scc_stack_[0] + scc_stack_.size());
162 for (
int i = current_scc_start - 1; i < scc_stack_.size(); ++i) {
163 node_index_[scc_stack_[i]] = kSettledIndex;
165 scc_stack_.resize(current_scc_start - 1);
166 scc_start_index_.pop_back();
168 scc_start_index_.empty() ? 0 : scc_start_index_.back();
171 }
while (!node_to_process_.empty());
179 return node_index_[node] > 0 && node_index_[node] < kSettledIndex;
183 static constexpr
NodeIndex kSettledIndex =
184 std::numeric_limits<NodeIndex>::max();
189 std::vector<NodeIndex> scc_stack_;
195 std::vector<NodeIndex> scc_start_index_;
203 std::vector<NodeIndex> node_index_;
208 std::vector<NodeIndex> node_to_process_;
212 template <
typename NodeIndex,
typename Graph,
typename SccOutput>
215 SccOutput* components) {
220 #endif // UTIL_GRAPH_STRONGLY_CONNECTED_COMPONENTS_H_