29 template <
typename IntQueue>
30 inline void PopTop(IntQueue* q,
int* top) {
35 template <
typename C,
typename F>
36 void PopTop(std::priority_queue<int, C, F>* q,
int* top) {
42 template <
bool stable_sort>
44 CHECK(!TraversalStarted()) <<
"Cannot add nodes after starting traversal";
46 if (node_index >= adjacency_lists_.size()) {
47 adjacency_lists_.resize(node_index + 1);
61 template <
bool stable_sort>
63 CHECK(!TraversalStarted()) <<
"Cannot add edges after starting traversal";
68 const uint32 adj_list_size = adj_list.size();
70 for (AdjacencyList::const_iterator it = adj_list.begin();
71 it != adj_list.end(); ++it) {
76 adj_list.push_back(to);
79 adj_list.push_back(to);
80 if (++num_edges_added_since_last_duplicate_removal_ > ++num_edges_ / 2) {
81 num_edges_added_since_last_duplicate_removal_ = 0;
86 num_edges_ -= RemoveDuplicates(&adjacency_lists_,
92 template <
bool stable_sort>
94 int* next_node_index,
bool* cyclic, std::vector<int>* output_cycle_nodes) {
95 if (!TraversalStarted()) {
100 if (num_nodes_left_ == 0) {
103 if (nodes_with_zero_indegree_.empty()) {
104 VLOG(2) <<
"Not all nodes have been visited (" << num_nodes_left_
105 <<
" nodes left), but there aren't any zero-indegree nodes"
106 <<
" available. This graph is cyclic! Use ExtractCycle() for"
107 <<
" more information.";
109 if (output_cycle_nodes != NULL) {
110 ExtractCycle(output_cycle_nodes);
117 PopTop(&nodes_with_zero_indegree_, next_node_index);
122 adj_list.swap(adjacency_lists_[*next_node_index]);
125 for (
int i = 0; i < adj_list.size(); ++i) {
126 if (--indegree_[adj_list[i]] == 0) {
127 nodes_with_zero_indegree_.push(adj_list[i]);
133 template <
bool stable_sort>
135 if (TraversalStarted()) {
139 const int num_nodes = adjacency_lists_.size();
140 indegree_.assign(num_nodes, 0);
146 for (
int from = 0; from < num_nodes; ++from) {
148 for (AdjacencyList::const_iterator it = adj_list.begin();
149 it != adj_list.end(); ++it) {
155 for (
int node = 0; node < num_nodes; ++node) {
156 if (indegree_[node] == 0) {
157 nodes_with_zero_indegree_.push(node);
161 num_nodes_left_ = num_nodes;
162 traversal_started_ =
true;
166 template <
bool stable_sort>
168 std::vector<AdjacencyList>* lists,
int skip_lists_smaller_than) {
170 if (skip_lists_smaller_than < 2) {
171 skip_lists_smaller_than = 2;
173 const int n = lists->size();
174 std::vector<bool> visited(n,
false);
175 int num_duplicates_removed = 0;
176 for (std::vector<AdjacencyList>::iterator list = lists->begin();
177 list != lists->end(); ++list) {
178 if (list->size() < skip_lists_smaller_than) {
181 num_duplicates_removed += list->size();
185 AdjacencyList::iterator it = list->begin();
186 DCHECK(it != list->end());
187 while (!visited[*it]) {
188 visited[*(it++)] =
true;
189 if (it == list->end()) {
194 if (it != list->end()) {
195 AdjacencyList::iterator it2 = it;
196 while (++it != list->end()) {
202 list->erase(it2, list->end());
204 for (it = list->begin(); it != list->end(); ++it) {
205 visited[*it] =
false;
207 num_duplicates_removed -= list->size();
209 return num_duplicates_removed;
216 template <
bool stable_sort>
218 std::vector<int>* cycle_nodes)
const {
219 const int num_nodes = adjacency_lists_.size();
220 cycle_nodes->clear();
225 std::vector<bool> no_cycle_reachable_from(num_nodes,
false);
232 explicit DfsState(
int _node) : node(_node), adj_list_index(0) {}
234 std::vector<DfsState> dfs_stack;
235 std::vector<bool> in_cur_stack(num_nodes,
false);
236 for (
int start_node = 0; start_node < num_nodes; ++start_node) {
237 if (no_cycle_reachable_from[start_node]) {
241 dfs_stack.push_back(DfsState(start_node));
242 in_cur_stack[start_node] =
true;
243 while (!dfs_stack.empty()) {
244 DfsState* cur_state = &dfs_stack.back();
245 if (cur_state->adj_list_index >=
246 adjacency_lists_[cur_state->node].size()) {
247 no_cycle_reachable_from[cur_state->node] =
true;
248 in_cur_stack[cur_state->node] =
false;
249 dfs_stack.pop_back();
255 adjacency_lists_[cur_state->node][cur_state->adj_list_index];
256 ++(cur_state->adj_list_index);
257 if (no_cycle_reachable_from[child]) {
260 if (in_cur_stack[child]) {
263 cycle_nodes->push_back(dfs_stack.back().node);
264 if (dfs_stack.back().node == child) {
265 std::reverse(cycle_nodes->begin(), cycle_nodes->end());
268 dfs_stack.pop_back();
272 dfs_stack.push_back(DfsState(child));
273 in_cur_stack[child] =
true;
289 int num_nodes,
const std::vector<std::pair<int, int>>& arcs) {
290 std::vector<int> cycle;
295 for (
const auto& arc : arcs) {
296 sorter.
AddEdge(arc.first, arc.second);