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>
107 SccOutput* components) {
111 std::vector<NodeIndex> scc_stack;
117 std::vector<NodeIndex> scc_start_index;
129 std::vector<NodeIndex> node_index(num_nodes, 0);
130 constexpr
NodeIndex kSettledIndex = std::numeric_limits<NodeIndex>::max();
135 std::vector<NodeIndex> node_to_process;
138 for (
NodeIndex base_node = 0; base_node < num_nodes; ++base_node) {
139 if (node_index[base_node] != 0)
continue;
140 DCHECK_EQ(0, node_to_process.size());
141 node_to_process.push_back(base_node);
143 const NodeIndex node = node_to_process.back();
144 const NodeIndex index = node_index[node];
147 scc_stack.push_back(node);
148 current_scc_start = scc_stack.size();
149 node_index[node] = current_scc_start;
150 scc_start_index.push_back(current_scc_start);
153 NodeIndex min_head_index = kSettledIndex;
154 for (
const NodeIndex head : graph[node]) {
155 const NodeIndex head_index = node_index[head];
156 if (head_index == 0) {
157 node_to_process.push_back(head);
160 min_head_index = std::min(min_head_index, head_index);
167 while (current_scc_start > min_head_index) {
168 scc_start_index.pop_back();
169 current_scc_start = scc_start_index.back();
172 node_to_process.pop_back();
173 if (current_scc_start == index) {
175 components->emplace_back(&scc_stack[current_scc_start - 1],
176 &scc_stack[0] + scc_stack.size());
177 for (
int i = current_scc_start - 1; i < scc_stack.size(); ++i) {
178 node_index[scc_stack[i]] = kSettledIndex;
180 scc_stack.resize(current_scc_start - 1);
181 scc_start_index.pop_back();
183 scc_start_index.empty() ? 0 : scc_start_index.back();
186 }
while (!node_to_process.empty());
190 #endif // UTIL_GRAPH_STRONGLY_CONNECTED_COMPONENTS_H_
int size() const
This is just here so this class can transparently replace a code that use std::vector<std::vector<int...
ListGraph Graph
Defining the simplest Graph interface as Graph for convenience.
void FindStronglyConnectedComponents(const NodeIndex num_nodes, const Graph &graph, SccOutput *components)
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in c...
A simple custom output class that just counts the number of SCC.
void emplace_back(NodeIndex const *b, NodeIndex const *e)
int32 NodeIndex
Standard instantiation of ForwardEbertGraph (named 'ForwardStarGraph') of EbertGraph (named 'StarGrap...