OR-Tools  9.1
graph.h
Go to the documentation of this file.
1// Copyright 2010-2021 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14//
15//
16// This file defines a generic graph interface on which most algorithms can be
17// built and provides a few efficient implementations with a fast construction
18// time. Its design is based on the experience acquired by the Operations
19// Research team in their various graph algorithm implementations.
20//
21// The main ideas are:
22// - Graph nodes and arcs are represented by integers.
23// - Node or arc annotations (weight, cost, ...) are not part of the graph
24// class, they can be stored outside in one or more arrays and can be easily
25// retrieved using a node or arc as an index.
26//
27// Terminology:
28// - An arc of a graph is directed and going from a tail node to a head node.
29// - Some implementations also store 'reverse' arcs and can be used for
30// undirected graph or flow-like algorithm.
31// - A node or arc index is 'valid' if it represents a node or arc of
32// the graph. The validity ranges are always [0, num_nodes()) for nodes and
33// [0, num_arcs()) for forward arcs. Reverse arcs are elements of
34// [-num_arcs(), 0) and are also considered valid by the implementations that
35// store them.
36//
37// Provided implementations:
38// - ListGraph<> for the simplest api. Also aliased to util::Graph.
39// - StaticGraph<> for performance, but require calling Build(), see below
40// - CompleteGraph<> if you need a fully connected graph
41// - CompleteBipartiteGraph<> if you need a fully connected bipartite graph
42// - ReverseArcListGraph<> to add reverse arcs to ListGraph<>
43// - ReverseArcStaticGraph<> to add reverse arcs to StaticGraph<>
44// - ReverseArcMixedGraph<> for a smaller memory footprint
45//
46// Utility classes & functions:
47// - Permute() to permute an array according to a given permutation.
48// - SVector<> vector with index range [-size(), size()) for ReverseArcGraph.
49//
50// Basic usage:
51// typedef ListGraph<> Graph; // Choose a graph implementation.
52// Graph graph;
53// for (...) {
54// graph.AddArc(tail, head);
55// }
56// ...
57// for (int node = 0; node < graph.num_nodes(); ++node) {
58// for (const int arc : graph.OutgoingArcs(node)) {
59// head = graph.Head(arc);
60// tail = node; // or graph.Tail(arc) which is fast but not as much.
61// }
62// }
63//
64// Iteration over the arcs touching a node:
65//
66// - OutgoingArcs(node): All the forward arcs leaving the node.
67// - IncomingArcs(node): All the forward arcs arriving at the node.
68//
69// And two more involved ones:
70//
71// - OutgoingOrOppositeIncomingArcs(node): This returns both the forward arcs
72// leaving the node (i.e. OutgoingArcs(node)) and the reverse arcs leaving the
73// node (i.e. the opposite arcs of the ones returned by IncomingArcs(node)).
74// - OppositeIncomingArcs(node): This returns the reverse arcs leaving the node.
75//
76// Note on iteration efficiency: When re-indexing the arcs it is not possible to
77// have both the outgoing arcs and the incoming ones form a consecutive range.
78//
79// It is however possible to do so for the outgoing arcs and the opposite
80// incoming arcs. It is why the OutgoingOrOppositeIncomingArcs() and
81// OutgoingArcs() iterations are more efficient than the IncomingArcs() one.
82//
83// If you know the graph size in advance, this already set the number of nodes,
84// reserve space for the arcs and check in DEBUG mode that you don't go over the
85// bounds:
86// Graph graph(num_nodes, arc_capacity);
87//
88// Storing and using node annotations:
89// vector<bool> is_visited(graph.num_nodes(), false);
90// ...
91// for (int node = 0; node < graph.num_nodes(); ++node) {
92// if (!is_visited[node]) ...
93// }
94//
95// Storing and using arc annotations:
96// vector<int> weights;
97// for (...) {
98// graph.AddArc(tail, head);
99// weights.push_back(arc_weight);
100// }
101// ...
102// for (const int arc : graph.OutgoingArcs(node)) {
103// ... weights[arc] ...;
104// }
105//
106// More efficient version:
107// typedef StaticGraph<> Graph;
108// Graph graph(num_nodes, arc_capacity); // Optional, but help memory usage.
109// vector<int> weights;
110// weights.reserve(arc_capacity); // Optional, but help memory usage.
111// for (...) {
112// graph.AddArc(tail, head);
113// weights.push_back(arc_weight);
114// }
115// ...
116// vector<Graph::ArcIndex> permutation;
117// graph.Build(&permutation); // A static graph must be Build() before usage.
118// Permute(permutation, &weights); // Build() may permute the arc index.
119// ...
120//
121// Encoding an undirected graph: If you don't need arc annotation, then the best
122// is to add two arcs for each edge (one in each direction) to a directed graph.
123// Otherwise you can do the following.
124//
125// typedef ReverseArc... Graph;
126// Graph graph;
127// for (...) {
128// graph.AddArc(tail, head); // or graph.AddArc(head, tail) but not both.
129// edge_annotations.push_back(value);
130// }
131// ...
132// for (const Graph::NodeIndex node : graph.AllNodes()) {
133// for (const Graph::ArcIndex arc :
134// graph.OutgoingOrOppositeIncomingArcs(node)) {
135// destination = graph.Head(arc);
136// annotation = edge_annotations[arc < 0 ? graph.OppositeArc(arc) : arc];
137// }
138// }
139//
140//
141// Note: The graphs are primarily designed to be constructed first and then used
142// because it covers most of the use cases. It is possible to extend the
143// interface with more dynamicity (like removing arcs), but this is not done at
144// this point. Note that a "dynamic" implementation will break some assumptions
145// we make on what node or arc are valid and also on the indices returned by
146// AddArc(). Some arguments for simplifying the interface at the cost of
147// dynamicity are:
148//
149// - It is always possible to construct a static graph from a dynamic one
150// before calling a complex algo.
151// - If you really need a dynamic graph, maybe it is better to compute a graph
152// property incrementally rather than calling an algorithm that starts from
153// scratch each time.
154
155#ifndef UTIL_GRAPH_GRAPH_H_
156#define UTIL_GRAPH_GRAPH_H_
157
158#include <algorithm>
159#include <cstddef>
160#include <cstdint>
161#include <cstdlib>
162#include <limits>
163#include <new>
164#include <vector>
165
166#include "absl/debugging/leak_check.h"
168#include "ortools/base/logging.h"
169#include "ortools/base/macros.h"
171
172namespace util {
173
174// Forward declaration.
175template <typename T>
176class SVector;
177
178// Base class of all Graphs implemented here. The default value for the graph
179// index types is int32_t since almost all graphs that fit into memory do not
180// need bigger indices.
181//
182// Note: The type can be unsigned, except for the graphs with reverse arcs
183// where the ArcIndexType must be signed, but not necessarly the NodeIndexType.
184template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t,
185 bool HasReverseArcs = false>
187 public:
188 // Typedef so you can use Graph::NodeIndex and Graph::ArcIndex to be generic
189 // but also to improve the readability of your code. We also recommend
190 // that you define a typedef ... Graph; for readability.
191 typedef NodeIndexType NodeIndex;
192 typedef ArcIndexType ArcIndex;
193
195 : num_nodes_(0),
197 num_arcs_(0),
198 arc_capacity_(0),
199 const_capacities_(false) {}
200 virtual ~BaseGraph() {}
201
202 // Returns the number of valid nodes in the graph.
203 NodeIndexType num_nodes() const { return num_nodes_; }
204
205 // Returns the number of valid arcs in the graph.
206 ArcIndexType num_arcs() const { return num_arcs_; }
207
208 // Allows nice range-based for loop:
209 // for (const NodeIndex node : graph.AllNodes()) { ... }
210 // for (const ArcIndex arc : graph.AllForwardArcs()) { ... }
213
214 // Returns true if the given node is a valid node of the graph.
215 bool IsNodeValid(NodeIndexType node) const {
216 return node >= 0 && node < num_nodes_;
217 }
218
219 // Returns true if the given arc is a valid arc of the graph.
220 // Note that the arc validity range changes for graph with reverse arcs.
221 bool IsArcValid(ArcIndexType arc) const {
222 return (HasReverseArcs ? -num_arcs_ : 0) <= arc && arc < num_arcs_;
223 }
224
225 // Capacity reserved for future nodes, always >= num_nodes_.
226 NodeIndexType node_capacity() const;
227
228 // Capacity reserved for future arcs, always >= num_arcs_.
229 ArcIndexType arc_capacity() const;
230
231 // Changes the graph capacities. The functions will fail in debug mode if:
232 // - const_capacities_ is true.
233 // - A valid node does not fall into the new node range.
234 // - A valid arc does not fall into the new arc range.
235 // In non-debug mode, const_capacities_ is ignored and nothing will happen
236 // if the new capacity value for the arcs or the nodes is too small.
237 virtual void ReserveNodes(NodeIndexType bound) {
240 if (bound <= num_nodes_) return;
242 }
243 virtual void ReserveArcs(ArcIndexType bound) {
246 if (bound <= num_arcs_) return;
248 }
249 void Reserve(NodeIndexType node_capacity, ArcIndexType arc_capacity) {
252 }
253
254 // FreezeCapacities() makes any future attempt to change the graph capacities
255 // crash in DEBUG mode.
257
258 // Constants that will never be a valid node or arc.
259 // They are the maximum possible node and arc capacity.
260 static const NodeIndexType kNilNode;
261 static const ArcIndexType kNilArc;
262
263 // TODO(user): remove the public functions below. They are just here during
264 // the transition from the old ebert_graph api to this new graph api.
265 template <typename A, typename B>
266 void GroupForwardArcsByFunctor(const A& a, B* b) {
267 LOG(FATAL) << "Not supported";
268 }
269 ArcIndexType max_end_arc_index() const { return arc_capacity_; }
270
271 protected:
272 // Functions commented when defined because they are implementation details.
273 void ComputeCumulativeSum(std::vector<ArcIndexType>* v);
275 std::vector<ArcIndexType>* start,
276 std::vector<ArcIndexType>* permutation);
277
278 NodeIndexType num_nodes_;
279 NodeIndexType node_capacity_;
280 ArcIndexType num_arcs_;
281 ArcIndexType arc_capacity_;
283};
284
285// Basic graph implementation without reverse arc. This class also serves as a
286// documentation for the generic graph interface (minus the part related to
287// reverse arcs).
288//
289// This implementation uses a linked list and compared to StaticGraph:
290// - Is a bit faster to construct (if the arcs are not ordered by tail).
291// - Does not require calling Build().
292// - Has slower outgoing arc iteration.
293// - Uses more memory: ArcIndexType * node_capacity()
294// + (ArcIndexType + NodeIndexType) * arc_capacity().
295// - Has an efficient Tail() but need an extra NodeIndexType/arc memory for it.
296// - Never changes the initial arc index returned by AddArc().
297//
298template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
299class ListGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
304 using Base::num_arcs_;
305 using Base::num_nodes_;
306
307 public:
308 using Base::IsArcValid;
310
311 // Reserve space for the graph at construction and do not allow it to grow
312 // beyond that, see FreezeCapacities(). This constructor also makes any nodes
313 // in [0, num_nodes) valid.
314 ListGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity) {
315 this->Reserve(num_nodes, arc_capacity);
316 this->FreezeCapacities();
317 this->AddNode(num_nodes - 1);
318 }
319
320 // If node is not a valid node, sets num_nodes_ to node + 1 so that the given
321 // node becomes valid. It will fail in DEBUG mode if the capacities are fixed
322 // and the new node is out of range.
323 void AddNode(NodeIndexType node);
324
325 // Adds an arc to the graph and returns its current index which will always
326 // be num_arcs() - 1. It will also automatically call AddNode(tail)
327 // and AddNode(head). It will fail in DEBUG mode if the capacities
328 // are fixed and this cause the graph to grow beyond them.
329 //
330 // Note: Self referencing arcs and duplicate arcs are supported.
331 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
332
333 // Some graph implementations need to be finalized with Build() before they
334 // can be used. After Build() is called, the arc indices (which had been the
335 // return values of previous AddArc() calls) may change: the new index of
336 // former arc #i will be stored in permutation[i] if #i is smaller than
337 // permutation.size() or will be unchanged otherwise. If you don't care about
338 // these, just call the simple no-output version Build().
339 //
340 // Note that some implementations become immutable after calling Build().
341 void Build() { Build(nullptr); }
342 void Build(std::vector<ArcIndexType>* permutation);
343
344 // Do not use directly.
345 class OutgoingArcIterator;
346 class OutgoingHeadIterator;
347
348 // Graph jargon: the "degree" of a node is its number of arcs. The out-degree
349 // is the number of outgoing arcs. The in-degree is the number of incoming
350 // arcs, and is only available for some graph implementations, below.
351 //
352 // ListGraph<>::OutDegree() works in O(degree).
353 ArcIndexType OutDegree(NodeIndexType node) const;
354
355 // Allows to iterate over the forward arcs that verify Tail(arc) == node.
356 // This is meant to be used as:
357 // for (const ArcIndex arc : graph.OutgoingArcs(node)) { ... }
359
360 // Advanced usage. Same as OutgoingArcs(), but allows to restart the iteration
361 // from an already known outgoing arc of the given node.
363 NodeIndexType node, ArcIndexType from) const;
364
365 // This loops over the heads of the OutgoingArcs(node). It is just a more
366 // convenient way to achieve this. Moreover this interface is used by some
367 // graph algorithms.
368 BeginEndWrapper<OutgoingHeadIterator> operator[](NodeIndexType node) const;
369
370 // Returns the tail/head of a valid arc.
371 NodeIndexType Tail(ArcIndexType arc) const;
372 NodeIndexType Head(ArcIndexType arc) const;
373
374 void ReserveNodes(NodeIndexType bound) override;
375 void ReserveArcs(ArcIndexType bound) override;
376
377 private:
378 std::vector<ArcIndexType> start_;
379 std::vector<ArcIndexType> next_;
380 std::vector<NodeIndexType> head_;
381 std::vector<NodeIndexType> tail_;
382};
383
384// Most efficient implementation of a graph without reverse arcs:
385// - Build() needs to be called after the arc and node have been added.
386// - The graph is really compact memory wise:
387// ArcIndexType * node_capacity() + 2 * NodeIndexType * arc_capacity(),
388// but when Build() is called it uses a temporary extra space of
389// ArcIndexType * arc_capacity().
390// - The construction is really fast.
391//
392// NOTE(user): if the need arises for very-well compressed graphs, we could
393// shave NodeIndexType * arc_capacity() off the permanent memory requirement
394// with a similar class that doesn't support Tail(), i.e.
395// StaticGraphWithoutTail<>. This almost corresponds to a past implementation
396// of StaticGraph<> @CL 116144340.
397template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
398class StaticGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
403 using Base::num_arcs_;
404 using Base::num_nodes_;
405
406 public:
407 using Base::IsArcValid;
408 StaticGraph() : is_built_(false), arc_in_order_(true), last_tail_seen_(0) {}
409 StaticGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
410 : is_built_(false), arc_in_order_(true), last_tail_seen_(0) {
411 this->Reserve(num_nodes, arc_capacity);
412 this->FreezeCapacities();
413 this->AddNode(num_nodes - 1);
414 }
415
416 // Do not use directly. See instead the arc iteration functions below.
417 class OutgoingArcIterator;
418
419 NodeIndexType Head(ArcIndexType arc) const;
420 NodeIndexType Tail(ArcIndexType arc) const;
421 ArcIndexType OutDegree(NodeIndexType node) const; // Work in O(1).
424 NodeIndexType node, ArcIndexType from) const;
425
426 // This loops over the heads of the OutgoingArcs(node). It is just a more
427 // convenient way to achieve this. Moreover this interface is used by some
428 // graph algorithms.
429 BeginEndWrapper<NodeIndexType const*> operator[](NodeIndexType node) const;
430
431 void ReserveNodes(NodeIndexType bound) override;
432 void ReserveArcs(ArcIndexType bound) override;
433 void AddNode(NodeIndexType node);
434 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
435
436 void Build() { Build(nullptr); }
437 void Build(std::vector<ArcIndexType>* permutation);
438
439 private:
440 ArcIndexType DirectArcLimit(NodeIndexType node) const {
441 DCHECK(is_built_);
443 return node + 1 < num_nodes_ ? start_[node + 1] : num_arcs_;
444 }
445
446 bool is_built_;
447 bool arc_in_order_;
448 NodeIndexType last_tail_seen_;
449 std::vector<ArcIndexType> start_;
450 std::vector<NodeIndexType> head_;
451 std::vector<NodeIndexType> tail_;
452};
453
454// Extends the ListGraph by also storing the reverse arcs.
455// This class also documents the Graph interface related to reverse arc.
456// - NodeIndexType can be unsigned, but ArcIndexType must be signed.
457// - It has most of the same advantanges and disadvantages as ListGraph.
458// - It takes 2 * ArcIndexType * node_capacity()
459// + 2 * (ArcIndexType + NodeIndexType) * arc_capacity() memory.
460template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
462 : public BaseGraph<NodeIndexType, ArcIndexType, true> {
467 using Base::num_arcs_;
468 using Base::num_nodes_;
469
470 public:
471 using Base::IsArcValid;
473 ReverseArcListGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity) {
474 this->Reserve(num_nodes, arc_capacity);
475 this->FreezeCapacities();
476 this->AddNode(num_nodes - 1);
477 }
478
479 // Returns the opposite arc of a given arc. That is the reverse arc of the
480 // given forward arc or the forward arc of a given reverse arc.
481 ArcIndexType OppositeArc(ArcIndexType arc) const;
482
483 // Do not use directly. See instead the arc iteration functions below.
484 class OutgoingOrOppositeIncomingArcIterator;
485 class OppositeIncomingArcIterator;
486 class IncomingArcIterator;
487 class OutgoingArcIterator;
488 class OutgoingHeadIterator;
489
490 // ReverseArcListGraph<>::OutDegree() and ::InDegree() work in O(degree).
491 ArcIndexType OutDegree(NodeIndexType node) const;
492 ArcIndexType InDegree(NodeIndexType node) const;
493
494 // Arc iterations functions over the arcs touching a node (see the top-level
495 // comment for the different types). To be used as follows:
496 // for (const Graph::ArcIndex arc : IterationFunction(node)) { ... }
497 //
498 // The StartingFrom() version are similar, but restart the iteration from a
499 // given arc position (which must be valid in the iteration context).
503 OutgoingOrOppositeIncomingArcs(NodeIndexType node) const;
505 NodeIndexType node) const;
507 NodeIndexType node, ArcIndexType from) const;
509 NodeIndexType node, ArcIndexType from) const;
512 ArcIndexType from) const;
514 NodeIndexType node, ArcIndexType from) const;
515
516 // This loops over the heads of the OutgoingArcs(node). It is just a more
517 // convenient way to achieve this. Moreover this interface is used by some
518 // graph algorithms.
519 BeginEndWrapper<OutgoingHeadIterator> operator[](NodeIndexType node) const;
520
521 NodeIndexType Head(ArcIndexType arc) const;
522 NodeIndexType Tail(ArcIndexType arc) const;
523
524 void ReserveNodes(NodeIndexType bound) override;
525 void ReserveArcs(ArcIndexType bound) override;
526 void AddNode(NodeIndexType node);
527 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
528
529 void Build() { Build(nullptr); }
530 void Build(std::vector<ArcIndexType>* permutation);
531
532 private:
533 std::vector<ArcIndexType> start_;
534 std::vector<ArcIndexType> reverse_start_;
537};
538
539// StaticGraph with reverse arc.
540// - NodeIndexType can be unsigned, but ArcIndexType must be signed.
541// - It has most of the same advantanges and disadvantages as StaticGraph.
542// - It takes 2 * ArcIndexType * node_capacity()
543// + 2 * (ArcIndexType + NodeIndexType) * arc_capacity() memory.
544// - If the ArcIndexPermutation is needed, then an extra ArcIndexType *
545// arc_capacity() is needed for it.
546// - The reverse arcs from a node are sorted by head (so we could add a log()
547// time lookup function).
548template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
550 : public BaseGraph<NodeIndexType, ArcIndexType, true> {
555 using Base::num_arcs_;
556 using Base::num_nodes_;
557
558 public:
559 using Base::IsArcValid;
560 ReverseArcStaticGraph() : is_built_(false) {}
561 ReverseArcStaticGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
562 : is_built_(false) {
563 this->Reserve(num_nodes, arc_capacity);
564 this->FreezeCapacities();
565 this->AddNode(num_nodes - 1);
566 }
567
568 // Deprecated.
569 class OutgoingOrOppositeIncomingArcIterator;
570 class OppositeIncomingArcIterator;
571 class IncomingArcIterator;
572 class OutgoingArcIterator;
573
574 // ReverseArcStaticGraph<>::OutDegree() and ::InDegree() work in O(1).
575 ArcIndexType OutDegree(NodeIndexType node) const;
576 ArcIndexType InDegree(NodeIndexType node) const;
577
581 OutgoingOrOppositeIncomingArcs(NodeIndexType node) const;
583 NodeIndexType node) const;
585 NodeIndexType node, ArcIndexType from) const;
587 NodeIndexType node, ArcIndexType from) const;
590 ArcIndexType from) const;
592 NodeIndexType node, ArcIndexType from) const;
593
594 // This loops over the heads of the OutgoingArcs(node). It is just a more
595 // convenient way to achieve this. Moreover this interface is used by some
596 // graph algorithms.
597 BeginEndWrapper<NodeIndexType const*> operator[](NodeIndexType node) const;
598
599 ArcIndexType OppositeArc(ArcIndexType arc) const;
600 // TODO(user): support Head() and Tail() before Build(), like StaticGraph<>.
601 NodeIndexType Head(ArcIndexType arc) const;
602 NodeIndexType Tail(ArcIndexType arc) const;
603
604 void ReserveArcs(ArcIndexType bound) override;
605 void AddNode(NodeIndexType node);
606 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
607
608 void Build() { Build(nullptr); }
609 void Build(std::vector<ArcIndexType>* permutation);
610
611 private:
612 ArcIndexType DirectArcLimit(NodeIndexType node) const {
613 DCHECK(is_built_);
615 return node + 1 < num_nodes_ ? start_[node + 1] : num_arcs_;
616 }
617 ArcIndexType ReverseArcLimit(NodeIndexType node) const {
618 DCHECK(is_built_);
620 return node + 1 < num_nodes_ ? reverse_start_[node + 1] : 0;
621 }
622
623 bool is_built_;
624 std::vector<ArcIndexType> start_;
625 std::vector<ArcIndexType> reverse_start_;
626 SVector<NodeIndexType> head_;
627 SVector<ArcIndexType> opposite_;
628};
629
630// This graph is a mix between the ReverseArcListGraph and the
631// ReverseArcStaticGraph. It uses less memory:
632// - It takes 2 * ArcIndexType * node_capacity()
633// + (2 * NodeIndexType + ArcIndexType) * arc_capacity() memory.
634// - If the ArcIndexPermutation is needed, then an extra ArcIndexType *
635// arc_capacity() is needed for it.
636template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
638 : public BaseGraph<NodeIndexType, ArcIndexType, true> {
643 using Base::num_arcs_;
644 using Base::num_nodes_;
645
646 public:
647 using Base::IsArcValid;
648 ReverseArcMixedGraph() : is_built_(false) {}
649 ReverseArcMixedGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
650 : is_built_(false) {
651 this->Reserve(num_nodes, arc_capacity);
652 this->FreezeCapacities();
653 this->AddNode(num_nodes - 1);
654 }
655
656 // Deprecated.
657 class OutgoingOrOppositeIncomingArcIterator;
658 class OppositeIncomingArcIterator;
659 class IncomingArcIterator;
660 class OutgoingArcIterator;
661
662 ArcIndexType OutDegree(NodeIndexType node) const; // O(1)
663 ArcIndexType InDegree(NodeIndexType node) const; // O(in-degree)
664
668 OutgoingOrOppositeIncomingArcs(NodeIndexType node) const;
670 NodeIndexType node) const;
672 NodeIndexType node, ArcIndexType from) const;
674 NodeIndexType node, ArcIndexType from) const;
677 ArcIndexType from) const;
679 NodeIndexType node, ArcIndexType from) const;
680
681 // This loops over the heads of the OutgoingArcs(node). It is just a more
682 // convenient way to achieve this. Moreover this interface is used by some
683 // graph algorithms.
684 BeginEndWrapper<NodeIndexType const*> operator[](NodeIndexType node) const;
685
686 ArcIndexType OppositeArc(ArcIndexType arc) const;
687 // TODO(user): support Head() and Tail() before Build(), like StaticGraph<>.
688 NodeIndexType Head(ArcIndexType arc) const;
689 NodeIndexType Tail(ArcIndexType arc) const;
690
691 void ReserveArcs(ArcIndexType bound) override;
692 void AddNode(NodeIndexType node);
693 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
694
695 void Build() { Build(nullptr); }
696 void Build(std::vector<ArcIndexType>* permutation);
697
698 private:
699 ArcIndexType DirectArcLimit(NodeIndexType node) const {
700 DCHECK(is_built_);
702 return node + 1 < num_nodes_ ? start_[node + 1] : num_arcs_;
703 }
704
705 bool is_built_;
706 std::vector<ArcIndexType> start_;
707 std::vector<ArcIndexType> reverse_start_;
708 std::vector<ArcIndexType> next_;
709 SVector<NodeIndexType> head_;
710};
711
712// Permutes the elements of array_to_permute: element #i will be moved to
713// position permutation[i]. permutation must be either empty (in which case
714// nothing happens), or a permutation of [0, permutation.size()).
715//
716// The algorithm is fast but need extra memory for a copy of the permuted part
717// of array_to_permute.
718//
719// TODO(user): consider slower but more memory efficient implementations that
720// follow the cycles of the permutation and use a bitmap to indicate what has
721// been permuted or to mark the beginning of each cycle.
722
723// Some compiler do not know typeof(), so we have to use this extra function
724// internally.
725template <class IntVector, class Array, class ElementType>
726void PermuteWithExplicitElementType(const IntVector& permutation,
727 Array* array_to_permute,
728 ElementType unused) {
729 std::vector<ElementType> temp(permutation.size());
730 for (int i = 0; i < permutation.size(); ++i) {
731 temp[i] = (*array_to_permute)[i];
732 }
733 for (int i = 0; i < permutation.size(); ++i) {
734 (*array_to_permute)[permutation[i]] = temp[i];
735 }
736}
737
738template <class IntVector, class Array>
739void Permute(const IntVector& permutation, Array* array_to_permute) {
740 if (permutation.empty()) {
741 return;
742 }
743 PermuteWithExplicitElementType(permutation, array_to_permute,
744 (*array_to_permute)[0]);
745}
746
747// We need a specialization for vector<bool>, because the default code uses
748// (*array_to_permute)[0] as ElementType, which isn't 'bool' in that case.
749template <class IntVector>
750void Permute(const IntVector& permutation,
751 std::vector<bool>* array_to_permute) {
752 if (permutation.empty()) {
753 return;
754 }
755 bool unused = false;
756 PermuteWithExplicitElementType(permutation, array_to_permute, unused);
757}
758
759// A vector-like class where valid indices are in [- size_, size_) and reserved
760// indices for future growth are in [- capacity_, capacity_). It is used to hold
761// arc related information for graphs with reverse arcs.
762// It supports only up to 2^31-1 elements, for compactness. If you ever need
763// more, consider using templates for the size/capacity integer types.
764//
765// Sample usage:
766//
767// SVector<int> v;
768// v.grow(left_value, right_value);
769// v.resize(10);
770// v.clear();
771// v.swap(new_v);
772// std:swap(v[i], v[~i]);
773template <typename T>
774class SVector {
775 public:
776 SVector() : base_(nullptr), size_(0), capacity_(0) {}
777
779
780 // Copy constructor and assignment operator.
781 SVector(const SVector& other) : SVector() { *this = other; }
782 SVector& operator=(const SVector& other) {
783 if (capacity_ < other.size_) {
785 // NOTE(user): Alternatively, our capacity could inherit from the other
786 // vector's capacity, which can be (much) greater than its size.
787 capacity_ = other.size_;
788 base_ = Allocate(capacity_);
789 CHECK(base_ != nullptr);
790 base_ += capacity_;
791 } else { // capacity_ >= other.size
792 clear();
793 }
794 // Perform the actual copy of the payload.
795 size_ = other.size_;
796 for (int i = -size_; i < size_; ++i) {
797 new (base_ + i) T(other.base_[i]);
798 }
799 return *this;
800 }
801
802 // Move constructor and move assignment operator.
803 SVector(SVector&& other) : SVector() { swap(other); }
805 // NOTE(user): We could just swap() and let the other's destruction take
806 // care of the clean-up, but it is probably less bug-prone to perform the
807 // destruction immediately.
809 swap(other);
810 return *this;
811 }
812
813 T& operator[](int n) {
814 DCHECK_LT(n, size_);
815 DCHECK_GE(n, -size_);
816 return base_[n];
817 }
818
819 const T& operator[](int n) const {
820 DCHECK_LT(n, size_);
821 DCHECK_GE(n, -size_);
822 return base_[n];
823 }
824
825 void resize(int n) {
826 reserve(n);
827 for (int i = -n; i < -size_; ++i) {
828 new (base_ + i) T();
829 }
830 for (int i = size_; i < n; ++i) {
831 new (base_ + i) T();
832 }
833 for (int i = -size_; i < -n; ++i) {
834 base_[i].~T();
835 }
836 for (int i = n; i < size_; ++i) {
837 base_[i].~T();
838 }
839 size_ = n;
840 }
841
842 void clear() { resize(0); }
843
844 T* data() const { return base_; }
845
846 void swap(SVector<T>& x) {
847 std::swap(base_, x.base_);
848 std::swap(size_, x.size_);
849 std::swap(capacity_, x.capacity_);
850 }
851
852 void reserve(int n) {
853 DCHECK_GE(n, 0);
854 DCHECK_LE(n, max_size());
855 if (n > capacity_) {
856 const int new_capacity = std::min(n, max_size());
857 T* new_storage = Allocate(new_capacity);
858 CHECK(new_storage != nullptr);
859 T* new_base = new_storage + new_capacity;
860 // TODO(user): in C++17 we could use std::uninitialized_move instead
861 // of this loop.
862 for (int i = -size_; i < size_; ++i) {
863 new (new_base + i) T(std::move(base_[i]));
864 }
865 int saved_size = size_;
867 size_ = saved_size;
868 base_ = new_base;
869 capacity_ = new_capacity;
870 }
871 }
872
873 // NOTE(user): This doesn't currently support movable-only objects, but we
874 // could fix that.
875 void grow(const T& left = T(), const T& right = T()) {
876 if (size_ == capacity_) {
877 // We have to copy the elements because they are allowed to be element of
878 // *this.
879 T left_copy(left); // NOLINT
880 T right_copy(right); // NOLINT
881 reserve(NewCapacity(1));
882 new (base_ + size_) T(right_copy);
883 new (base_ - size_ - 1) T(left_copy);
884 ++size_;
885 } else {
886 new (base_ + size_) T(right);
887 new (base_ - size_ - 1) T(left);
888 ++size_;
889 }
890 }
891
892 int size() const { return size_; }
893
894 int capacity() const { return capacity_; }
895
896 int max_size() const { return std::numeric_limits<int>::max(); }
897
899 if (base_ == nullptr) return;
900 clear();
901 if (capacity_ > 0) {
902 free(base_ - capacity_);
903 }
904 capacity_ = 0;
905 base_ = nullptr;
906 }
907
908 private:
909 T* Allocate(int capacity) const {
910 return absl::IgnoreLeak(
911 static_cast<T*>(malloc(2LL * capacity * sizeof(T))));
912 }
913
914 int NewCapacity(int delta) {
915 // TODO(user): check validity.
916 double candidate = 1.3 * static_cast<double>(capacity_);
917 if (candidate > static_cast<double>(max_size())) {
918 candidate = static_cast<double>(max_size());
919 }
920 int new_capacity = static_cast<int>(candidate);
921 if (new_capacity > capacity_ + delta) {
922 return new_capacity;
923 }
924 return capacity_ + delta;
925 }
926
927 T* base_; // Pointer to the element of index 0.
928 int size_; // Valid index are [- size_, size_).
929 int capacity_; // Reserved index are [- capacity_, capacity_).
930};
931
932// BaseGraph implementation ----------------------------------------------------
933
934template <typename NodeIndexType, typename ArcIndexType, bool HasReverseArcs>
935IntegerRange<NodeIndexType>
937 return IntegerRange<NodeIndexType>(0, num_nodes_);
938}
939
940template <typename NodeIndexType, typename ArcIndexType, bool HasReverseArcs>
943 return IntegerRange<ArcIndexType>(0, num_arcs_);
944}
945
946template <typename NodeIndexType, typename ArcIndexType, bool HasReverseArcs>
947const NodeIndexType
950
951template <typename NodeIndexType, typename ArcIndexType, bool HasReverseArcs>
952const ArcIndexType
955
956template <typename NodeIndexType, typename ArcIndexType, bool HasReverseArcs>
957NodeIndexType
959 // TODO(user): Is it needed? remove completely? return the real capacities
960 // at the cost of having a different implementation for each graphs?
961 return node_capacity_ > num_nodes_ ? node_capacity_ : num_nodes_;
962}
963
964template <typename NodeIndexType, typename ArcIndexType, bool HasReverseArcs>
965ArcIndexType
967 // TODO(user): Same questions as the ones in node_capacity().
968 return arc_capacity_ > num_arcs_ ? arc_capacity_ : num_arcs_;
969}
970
971template <typename NodeIndexType, typename ArcIndexType, bool HasReverseArcs>
972void BaseGraph<NodeIndexType, ArcIndexType,
973 HasReverseArcs>::FreezeCapacities() {
974 // TODO(user): Only define this in debug mode at the cost of having a lot
975 // of ifndef NDEBUG all over the place? remove the function completely ?
976 const_capacities_ = true;
977 node_capacity_ = std::max(node_capacity_, num_nodes_);
978 arc_capacity_ = std::max(arc_capacity_, num_arcs_);
979}
980
981// Computes the cumulative sum of the entry in v. We only use it with
982// in/out degree distribution, hence the Check() at the end.
983template <typename NodeIndexType, typename ArcIndexType, bool HasReverseArcs>
985 ComputeCumulativeSum(std::vector<ArcIndexType>* v) {
986 ArcIndexType sum = 0;
987 for (int i = 0; i < num_nodes_; ++i) {
988 ArcIndexType temp = (*v)[i];
989 (*v)[i] = sum;
990 sum += temp;
991 }
992 DCHECK(sum == num_arcs_);
993}
994
995// Given the tail of arc #i in (*head)[i] and the head of arc #i in (*head)[~i]
996// - Reorder the arc by increasing tail.
997// - Put the head of the new arc #i in (*head)[i].
998// - Put in start[i] the index of the first arc with tail >= i.
999// - Update "permutation" to reflect the change, unless it is NULL.
1000template <typename NodeIndexType, typename ArcIndexType, bool HasReverseArcs>
1003 std::vector<ArcIndexType>* start,
1004 std::vector<ArcIndexType>* permutation) {
1005 // Computes the outgoing degree of each nodes and check if we need to permute
1006 // something or not. Note that the tails are currently stored in the positive
1007 // range of the SVector head.
1008 start->assign(num_nodes_, 0);
1009 int last_tail_seen = 0;
1010 bool permutation_needed = false;
1011 for (int i = 0; i < num_arcs_; ++i) {
1012 NodeIndexType tail = (*head)[i];
1013 if (!permutation_needed) {
1014 permutation_needed = tail < last_tail_seen;
1015 last_tail_seen = tail;
1016 }
1017 (*start)[tail]++;
1018 }
1019 ComputeCumulativeSum(start);
1020
1021 // Abort early if we do not need the permutation: we only need to put the
1022 // heads in the positive range.
1023 if (!permutation_needed) {
1024 for (int i = 0; i < num_arcs_; ++i) {
1025 (*head)[i] = (*head)[~i];
1026 }
1027 if (permutation != nullptr) {
1028 permutation->clear();
1029 }
1030 return;
1031 }
1032
1033 // Computes the forward arc permutation.
1034 // Note that this temporarily alters the start vector.
1035 std::vector<ArcIndexType> perm(num_arcs_);
1036 for (int i = 0; i < num_arcs_; ++i) {
1037 perm[i] = (*start)[(*head)[i]]++;
1038 }
1039
1040 // Restore in (*start)[i] the index of the first arc with tail >= i.
1041 for (int i = num_nodes_ - 1; i > 0; --i) {
1042 (*start)[i] = (*start)[i - 1];
1043 }
1044 (*start)[0] = 0;
1045
1046 // Permutes the head into their final position in head.
1047 // We do not need the tails anymore at this point.
1048 for (int i = 0; i < num_arcs_; ++i) {
1049 (*head)[perm[i]] = (*head)[~i];
1050 }
1051 if (permutation != nullptr) {
1052 permutation->swap(perm);
1053 }
1054}
1055
1056// ---------------------------------------------------------------------------
1057// Macros to wrap old style iteration into the new range-based for loop style.
1058// ---------------------------------------------------------------------------
1059
1060// The parameters are:
1061// - c: the class name.
1062// - t: the iteration type (Outgoing, Incoming, OutgoingOrOppositeIncoming
1063// or OppositeIncoming).
1064// - e: the "end" ArcIndexType.
1065#define DEFINE_RANGE_BASED_ARC_ITERATION(c, t, e) \
1066 template <typename NodeIndexType, typename ArcIndexType> \
1067 BeginEndWrapper<typename c<NodeIndexType, ArcIndexType>::t##ArcIterator> \
1068 c<NodeIndexType, ArcIndexType>::t##Arcs(NodeIndexType node) const { \
1069 return BeginEndWrapper<t##ArcIterator>(t##ArcIterator(*this, node), \
1070 t##ArcIterator(*this, node, e)); \
1071 } \
1072 template <typename NodeIndexType, typename ArcIndexType> \
1073 BeginEndWrapper<typename c<NodeIndexType, ArcIndexType>::t##ArcIterator> \
1074 c<NodeIndexType, ArcIndexType>::t##ArcsStartingFrom( \
1075 NodeIndexType node, ArcIndexType from) const { \
1076 return BeginEndWrapper<t##ArcIterator>(t##ArcIterator(*this, node, from), \
1077 t##ArcIterator(*this, node, e)); \
1078 }
1079
1080// Adapt our old iteration style to support range-based for loops. Add typedefs
1081// required by std::iterator_traits.
1082#define DEFINE_STL_ITERATOR_FUNCTIONS(iterator_class_name) \
1083 using iterator_category = std::input_iterator_tag; \
1084 using difference_type = ptrdiff_t; \
1085 using pointer = const ArcIndexType*; \
1086 using reference = const ArcIndexType&; \
1087 using value_type = ArcIndexType; \
1088 bool operator!=(const iterator_class_name& other) const { \
1089 return this->index_ != other.index_; \
1090 } \
1091 bool operator==(const iterator_class_name& other) const { \
1092 return this->index_ == other.index_; \
1093 } \
1094 ArcIndexType operator*() const { return this->Index(); } \
1095 void operator++() { this->Next(); }
1096
1097// ListGraph implementation ----------------------------------------------------
1098
1100
1101template <typename NodeIndexType, typename ArcIndexType>
1106 OutgoingHeadIterator(*this, node),
1107 OutgoingHeadIterator(*this, node, Base::kNilArc));
1108}
1109
1110template <typename NodeIndexType, typename ArcIndexType>
1112 ArcIndexType arc) const {
1113 DCHECK(IsArcValid(arc));
1114 return tail_[arc];
1115}
1116
1117template <typename NodeIndexType, typename ArcIndexType>
1119 ArcIndexType arc) const {
1120 DCHECK(IsArcValid(arc));
1121 return head_[arc];
1122}
1123
1124template <typename NodeIndexType, typename ArcIndexType>
1126 NodeIndexType node) const {
1127 ArcIndexType degree(0);
1128 for (auto arc ABSL_ATTRIBUTE_UNUSED : OutgoingArcs(node)) ++degree;
1129 return degree;
1130}
1131
1132template <typename NodeIndexType, typename ArcIndexType>
1134 if (node < num_nodes_) return;
1135 DCHECK(!const_capacities_ || node < node_capacity_);
1136 num_nodes_ = node + 1;
1137 start_.resize(num_nodes_, Base::kNilArc);
1138}
1139
1140template <typename NodeIndexType, typename ArcIndexType>
1142 NodeIndexType tail, NodeIndexType head) {
1143 DCHECK_GE(tail, 0);
1144 DCHECK_GE(head, 0);
1145 AddNode(tail > head ? tail : head);
1146 head_.push_back(head);
1147 tail_.push_back(tail);
1148 next_.push_back(start_[tail]);
1149 start_[tail] = num_arcs_;
1150 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
1151 return num_arcs_++;
1152}
1153
1154template <typename NodeIndexType, typename ArcIndexType>
1156 Base::ReserveNodes(bound);
1157 if (bound <= num_nodes_) return;
1158 start_.reserve(bound);
1159}
1160
1161template <typename NodeIndexType, typename ArcIndexType>
1163 Base::ReserveArcs(bound);
1164 if (bound <= num_arcs_) return;
1165 head_.reserve(bound);
1166 tail_.reserve(bound);
1167 next_.reserve(bound);
1168}
1169
1170template <typename NodeIndexType, typename ArcIndexType>
1172 std::vector<ArcIndexType>* permutation) {
1173 if (permutation != nullptr) {
1174 permutation->clear();
1175 }
1176}
1177
1178template <typename NodeIndexType, typename ArcIndexType>
1179class ListGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
1180 public:
1181 OutgoingArcIterator(const ListGraph& graph, NodeIndexType node)
1182 : graph_(graph), index_(graph.start_[node]) {
1183 DCHECK(graph.IsNodeValid(node));
1184 }
1185 OutgoingArcIterator(const ListGraph& graph, NodeIndexType node,
1186 ArcIndexType arc)
1187 : graph_(graph), index_(arc) {
1188 DCHECK(graph.IsNodeValid(node));
1189 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
1190 }
1191 bool Ok() const { return index_ != Base::kNilArc; }
1192 ArcIndexType Index() const { return index_; }
1193 void Next() {
1194 DCHECK(Ok());
1195 index_ = graph_.next_[index_];
1196 }
1197
1199
1200 private:
1201 const ListGraph& graph_;
1202 ArcIndexType index_;
1203};
1204
1205template <typename NodeIndexType, typename ArcIndexType>
1206class ListGraph<NodeIndexType, ArcIndexType>::OutgoingHeadIterator {
1207 public:
1208 using iterator_category = std::input_iterator_tag;
1209 using difference_type = ptrdiff_t;
1210 using pointer = const NodeIndexType*;
1211 using reference = const NodeIndexType&;
1212 using value_type = NodeIndexType;
1213
1214 OutgoingHeadIterator(const ListGraph& graph, NodeIndexType node)
1215 : graph_(graph), index_(graph.start_[node]) {
1216 DCHECK(graph.IsNodeValid(node));
1217 }
1218 OutgoingHeadIterator(const ListGraph& graph, NodeIndexType node,
1219 ArcIndexType arc)
1220 : graph_(graph), index_(arc) {
1221 DCHECK(graph.IsNodeValid(node));
1222 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
1223 }
1224 bool Ok() const { return index_ != Base::kNilArc; }
1225 NodeIndexType Index() const { return graph_.Head(index_); }
1226 void Next() {
1227 DCHECK(Ok());
1228 index_ = graph_.next_[index_];
1229 }
1230
1232 const typename ListGraph<
1233 NodeIndexType, ArcIndexType>::OutgoingHeadIterator& other) const {
1234 return index_ != other.index_;
1235 }
1236 NodeIndexType operator*() const { return Index(); }
1237 void operator++() { Next(); }
1238
1239 private:
1240 const ListGraph& graph_;
1241 ArcIndexType index_;
1242};
1243
1244// StaticGraph implementation --------------------------------------------------
1245
1246DEFINE_RANGE_BASED_ARC_ITERATION(StaticGraph, Outgoing, DirectArcLimit(node));
1247
1248template <typename NodeIndexType, typename ArcIndexType>
1252 head_.data() + start_[node], head_.data() + DirectArcLimit(node));
1253}
1254
1255template <typename NodeIndexType, typename ArcIndexType>
1257 NodeIndexType node) const {
1258 return DirectArcLimit(node) - start_[node];
1259}
1260
1261template <typename NodeIndexType, typename ArcIndexType>
1263 NodeIndexType bound) {
1264 Base::ReserveNodes(bound);
1265 if (bound <= num_nodes_) return;
1266 start_.reserve(bound);
1267}
1268
1269template <typename NodeIndexType, typename ArcIndexType>
1271 Base::ReserveArcs(bound);
1272 if (bound <= num_arcs_) return;
1273 head_.reserve(bound);
1274 tail_.reserve(bound);
1275}
1276
1277template <typename NodeIndexType, typename ArcIndexType>
1279 if (node < num_nodes_) return;
1280 DCHECK(!const_capacities_ || node < node_capacity_) << node;
1281 num_nodes_ = node + 1;
1282 start_.resize(num_nodes_, 0);
1283}
1284
1285template <typename NodeIndexType, typename ArcIndexType>
1287 NodeIndexType tail, NodeIndexType head) {
1288 DCHECK_GE(tail, 0);
1289 DCHECK_GE(head, 0);
1290 DCHECK(!is_built_);
1291 AddNode(tail > head ? tail : head);
1292 if (arc_in_order_) {
1293 if (tail >= last_tail_seen_) {
1294 start_[tail]++;
1295 last_tail_seen_ = tail;
1296 } else {
1297 arc_in_order_ = false;
1298 }
1299 }
1300 tail_.push_back(tail);
1301 head_.push_back(head);
1302 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
1303 return num_arcs_++;
1304}
1305
1306template <typename NodeIndexType, typename ArcIndexType>
1308 ArcIndexType arc) const {
1309 DCHECK(IsArcValid(arc));
1310 return tail_[arc];
1311}
1312
1313template <typename NodeIndexType, typename ArcIndexType>
1315 ArcIndexType arc) const {
1316 DCHECK(IsArcValid(arc));
1317 return head_[arc];
1318}
1319
1320// Implementation details: A reader may be surprised that we do many passes
1321// into the data where things could be done in one pass. For instance, during
1322// construction, we store the edges first, and then do a second pass at the
1323// end to compute the degree distribution.
1324//
1325// This is because it is a lot more efficient cache-wise to do it this way.
1326// This was determined by various experiments, but can also be understood:
1327// - during repetitive call to AddArc() a client usually accesses various
1328// areas of memory, and there is no reason to polute the cache with
1329// possibly random access to degree[i].
1330// - When the degrees are needed, we compute them in one go, maximizing the
1331// chance of cache hit during the computation.
1332template <typename NodeIndexType, typename ArcIndexType>
1334 std::vector<ArcIndexType>* permutation) {
1335 DCHECK(!is_built_);
1336 if (is_built_) return;
1337 is_built_ = true;
1338 node_capacity_ = num_nodes_;
1339 arc_capacity_ = num_arcs_;
1340 this->FreezeCapacities();
1341
1342 // If Arc are in order, start_ already contains the degree distribution.
1343 if (arc_in_order_) {
1344 if (permutation != nullptr) {
1345 permutation->clear();
1346 }
1347 this->ComputeCumulativeSum(&start_);
1348 return;
1349 }
1350
1351 // Computes outgoing degree of each nodes. We have to clear start_, since
1352 // at least the first arc was processed with arc_in_order_ == true.
1353 start_.assign(num_nodes_, 0);
1354 for (int i = 0; i < num_arcs_; ++i) {
1355 start_[tail_[i]]++;
1356 }
1357 this->ComputeCumulativeSum(&start_);
1358
1359 // Computes the forward arc permutation.
1360 // Note that this temporarily alters the start_ vector.
1361 std::vector<ArcIndexType> perm(num_arcs_);
1362 for (int i = 0; i < num_arcs_; ++i) {
1363 perm[i] = start_[tail_[i]]++;
1364 }
1365
1366 // We use "tail_" (which now contains rubbish) to permute "head_" faster.
1367 CHECK_EQ(tail_.size(), num_arcs_);
1368 tail_.swap(head_);
1369 for (int i = 0; i < num_arcs_; ++i) {
1370 head_[perm[i]] = tail_[i];
1371 }
1372
1373 if (permutation != nullptr) {
1374 permutation->swap(perm);
1375 }
1376
1377 // Restore in start_[i] the index of the first arc with tail >= i.
1378 for (int i = num_nodes_ - 1; i > 0; --i) {
1379 start_[i] = start_[i - 1];
1380 }
1381 start_[0] = 0;
1382
1383 // Recompute the correct tail_ vector
1384 for (const NodeIndexType node : Base::AllNodes()) {
1385 for (const ArcIndexType arc : OutgoingArcs(node)) {
1386 tail_[arc] = node;
1387 }
1388 }
1389}
1390
1391template <typename NodeIndexType, typename ArcIndexType>
1392class StaticGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
1393 public:
1394 OutgoingArcIterator(const StaticGraph& graph, NodeIndexType node)
1395 : index_(graph.start_[node]), limit_(graph.DirectArcLimit(node)) {}
1396 OutgoingArcIterator(const StaticGraph& graph, NodeIndexType node,
1397 ArcIndexType arc)
1398 : index_(arc), limit_(graph.DirectArcLimit(node)) {
1399 DCHECK_GE(arc, graph.start_[node]);
1400 }
1401
1402 bool Ok() const { return index_ < limit_; }
1403 ArcIndexType Index() const { return index_; }
1404 void Next() {
1405 DCHECK(Ok());
1406 index_++;
1407 }
1408
1409 // Note(user): we lose a bit by returning a BeginEndWrapper<> on top of
1410 // this iterator rather than a simple IntegerRange<> on the arc indices.
1411 // On my computer: around 420M arcs/sec instead of 440M arcs/sec.
1412 //
1413 // However, it is slightly more consistent to do it this way, and we don't
1414 // have two different codes depending on the way a client iterates on the
1415 // arcs.
1417
1418 private:
1419 ArcIndexType index_;
1420 const ArcIndexType limit_;
1421};
1422
1423// ReverseArcListGraph implementation ------------------------------------------
1424
1428 OutgoingOrOppositeIncoming, Base::kNilArc);
1430 Base::kNilArc);
1431
1432template <typename NodeIndexType, typename ArcIndexType>
1434 NodeIndexType, ArcIndexType>::OutgoingHeadIterator>
1436 NodeIndexType node) const {
1438 OutgoingHeadIterator(*this, node),
1439 OutgoingHeadIterator(*this, node, Base::kNilArc));
1440}
1441
1442template <typename NodeIndexType, typename ArcIndexType>
1444 NodeIndexType node) const {
1445 ArcIndexType degree(0);
1446 for (auto arc ABSL_ATTRIBUTE_UNUSED : OutgoingArcs(node)) ++degree;
1447 return degree;
1448}
1449
1450template <typename NodeIndexType, typename ArcIndexType>
1452 NodeIndexType node) const {
1453 ArcIndexType degree(0);
1454 for (auto arc ABSL_ATTRIBUTE_UNUSED : OppositeIncomingArcs(node)) ++degree;
1455 return degree;
1456}
1457
1458template <typename NodeIndexType, typename ArcIndexType>
1460 ArcIndexType arc) const {
1461 DCHECK(IsArcValid(arc));
1462 return ~arc;
1463}
1464
1465template <typename NodeIndexType, typename ArcIndexType>
1467 ArcIndexType arc) const {
1468 DCHECK(IsArcValid(arc));
1469 return head_[arc];
1470}
1471
1472template <typename NodeIndexType, typename ArcIndexType>
1474 ArcIndexType arc) const {
1475 return head_[OppositeArc(arc)];
1476}
1477
1478template <typename NodeIndexType, typename ArcIndexType>
1480 NodeIndexType bound) {
1481 Base::ReserveNodes(bound);
1482 if (bound <= num_nodes_) return;
1483 start_.reserve(bound);
1484 reverse_start_.reserve(bound);
1485}
1486
1487template <typename NodeIndexType, typename ArcIndexType>
1489 ArcIndexType bound) {
1490 Base::ReserveArcs(bound);
1491 if (bound <= num_arcs_) return;
1492 head_.reserve(bound);
1493 next_.reserve(bound);
1494}
1495
1496template <typename NodeIndexType, typename ArcIndexType>
1498 NodeIndexType node) {
1499 if (node < num_nodes_) return;
1500 DCHECK(!const_capacities_ || node < node_capacity_);
1501 num_nodes_ = node + 1;
1502 start_.resize(num_nodes_, Base::kNilArc);
1503 reverse_start_.resize(num_nodes_, Base::kNilArc);
1504}
1505
1506template <typename NodeIndexType, typename ArcIndexType>
1508 NodeIndexType tail, NodeIndexType head) {
1509 DCHECK_GE(tail, 0);
1510 DCHECK_GE(head, 0);
1511 AddNode(tail > head ? tail : head);
1512 head_.grow(tail, head);
1513 next_.grow(reverse_start_[head], start_[tail]);
1514 start_[tail] = num_arcs_;
1515 reverse_start_[head] = ~num_arcs_;
1516 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
1517 return num_arcs_++;
1518}
1519
1520template <typename NodeIndexType, typename ArcIndexType>
1522 std::vector<ArcIndexType>* permutation) {
1523 if (permutation != nullptr) {
1524 permutation->clear();
1525 }
1526}
1527
1528template <typename NodeIndexType, typename ArcIndexType>
1529class ReverseArcListGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
1530 public:
1531 OutgoingArcIterator(const ReverseArcListGraph& graph, NodeIndexType node)
1532 : graph_(graph), index_(graph.start_[node]) {
1533 DCHECK(graph.IsNodeValid(node));
1534 }
1535 OutgoingArcIterator(const ReverseArcListGraph& graph, NodeIndexType node,
1536 ArcIndexType arc)
1537 : graph_(graph), index_(arc) {
1538 DCHECK(graph.IsNodeValid(node));
1539 DCHECK(arc == Base::kNilArc || arc >= 0);
1540 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
1541 }
1542 bool Ok() const { return index_ != Base::kNilArc; }
1543 ArcIndexType Index() const { return index_; }
1544 void Next() {
1545 DCHECK(Ok());
1546 index_ = graph_.next_[index_];
1547 }
1548
1550
1551 private:
1552 const ReverseArcListGraph& graph_;
1553 ArcIndexType index_;
1554};
1555
1556template <typename NodeIndexType, typename ArcIndexType>
1557class ReverseArcListGraph<NodeIndexType,
1558 ArcIndexType>::OppositeIncomingArcIterator {
1559 public:
1561 NodeIndexType node)
1562 : graph_(graph), index_(graph.reverse_start_[node]) {
1563 DCHECK(graph.IsNodeValid(node));
1564 }
1566 NodeIndexType node, ArcIndexType arc)
1567 : graph_(graph), index_(arc) {
1568 DCHECK(graph.IsNodeValid(node));
1569 DCHECK(arc == Base::kNilArc || arc < 0);
1570 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
1571 }
1572
1573 bool Ok() const { return index_ != Base::kNilArc; }
1574 ArcIndexType Index() const { return index_; }
1575 void Next() {
1576 DCHECK(Ok());
1577 index_ = graph_.next_[index_];
1578 }
1579
1581
1582 protected:
1584 ArcIndexType index_;
1585};
1586
1587template <typename NodeIndexType, typename ArcIndexType>
1588class ReverseArcListGraph<NodeIndexType, ArcIndexType>::IncomingArcIterator
1590 public:
1591 IncomingArcIterator(const ReverseArcListGraph& graph, NodeIndexType node)
1592 : OppositeIncomingArcIterator(graph, node) {}
1593 IncomingArcIterator(const ReverseArcListGraph& graph, NodeIndexType node,
1594 ArcIndexType arc)
1596 graph, node,
1597 arc == Base::kNilArc ? Base::kNilArc : graph.OppositeArc(arc)) {}
1598
1599 // We overwrite OppositeIncomingArcIterator::Index() here.
1600 ArcIndexType Index() const {
1601 return this->index_ == Base::kNilArc
1603 : this->graph_.OppositeArc(this->index_);
1604 }
1605
1607};
1608
1609template <typename NodeIndexType, typename ArcIndexType>
1610class ReverseArcListGraph<NodeIndexType,
1612 public:
1614 NodeIndexType node)
1615 : graph_(graph), index_(graph.reverse_start_[node]), node_(node) {
1616 DCHECK(graph.IsNodeValid(node));
1617 if (index_ == Base::kNilArc) index_ = graph.start_[node];
1618 }
1620 NodeIndexType node, ArcIndexType arc)
1621 : graph_(graph), index_(arc), node_(node) {
1622 DCHECK(graph.IsNodeValid(node));
1623 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
1624 }
1625
1626 bool Ok() const { return index_ != Base::kNilArc; }
1627 ArcIndexType Index() const { return index_; }
1628 void Next() {
1629 DCHECK(Ok());
1630 if (index_ < 0) {
1631 index_ = graph_.next_[index_];
1632 if (index_ == Base::kNilArc) {
1633 index_ = graph_.start_[node_];
1634 }
1635 } else {
1636 index_ = graph_.next_[index_];
1637 }
1638 }
1639
1641
1642 private:
1643 const ReverseArcListGraph& graph_;
1644 ArcIndexType index_;
1645 const NodeIndexType node_;
1646};
1647
1648template <typename NodeIndexType, typename ArcIndexType>
1649class ReverseArcListGraph<NodeIndexType, ArcIndexType>::OutgoingHeadIterator {
1650 public:
1651 OutgoingHeadIterator(const ReverseArcListGraph& graph, NodeIndexType node)
1652 : graph_(&graph), index_(graph.start_[node]) {
1653 DCHECK(graph.IsNodeValid(node));
1654 }
1655 OutgoingHeadIterator(const ReverseArcListGraph& graph, NodeIndexType node,
1656 ArcIndexType arc)
1657 : graph_(&graph), index_(arc) {
1658 DCHECK(graph.IsNodeValid(node));
1659 DCHECK(arc == Base::kNilArc || arc >= 0);
1660 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
1661 }
1662 bool Ok() const { return index_ != Base::kNilArc; }
1663 ArcIndexType Index() const { return graph_->Head(index_); }
1664 void Next() {
1665 DCHECK(Ok());
1666 index_ = graph_->next_[index_];
1667 }
1668
1670
1671 private:
1672 const ReverseArcListGraph* graph_;
1673 ArcIndexType index_;
1674};
1675
1676// ReverseArcStaticGraph implementation ----------------------------------------
1677
1679 DirectArcLimit(node));
1681 ReverseArcLimit(node));
1683 OutgoingOrOppositeIncoming,
1684 DirectArcLimit(node));
1686 ReverseArcLimit(node));
1687
1688template <typename NodeIndexType, typename ArcIndexType>
1690 NodeIndexType node) const {
1691 return DirectArcLimit(node) - start_[node];
1692}
1693
1694template <typename NodeIndexType, typename ArcIndexType>
1696 NodeIndexType node) const {
1697 return ReverseArcLimit(node) - reverse_start_[node];
1698}
1699
1700template <typename NodeIndexType, typename ArcIndexType>
1703 NodeIndexType node) const {
1705 head_.data() + start_[node], head_.data() + DirectArcLimit(node));
1706}
1707
1708template <typename NodeIndexType, typename ArcIndexType>
1710 ArcIndexType arc) const {
1711 DCHECK(is_built_);
1712 DCHECK(IsArcValid(arc));
1713 return opposite_[arc];
1714}
1715
1716template <typename NodeIndexType, typename ArcIndexType>
1718 ArcIndexType arc) const {
1719 DCHECK(is_built_);
1720 DCHECK(IsArcValid(arc));
1721 return head_[arc];
1722}
1723
1724template <typename NodeIndexType, typename ArcIndexType>
1726 ArcIndexType arc) const {
1727 DCHECK(is_built_);
1728 return head_[OppositeArc(arc)];
1729}
1730
1731template <typename NodeIndexType, typename ArcIndexType>
1733 ArcIndexType bound) {
1734 Base::ReserveArcs(bound);
1735 if (bound <= num_arcs_) return;
1736 head_.reserve(bound);
1737}
1738
1739template <typename NodeIndexType, typename ArcIndexType>
1741 NodeIndexType node) {
1742 if (node < num_nodes_) return;
1743 DCHECK(!const_capacities_ || node < node_capacity_);
1744 num_nodes_ = node + 1;
1745}
1746
1747template <typename NodeIndexType, typename ArcIndexType>
1749 NodeIndexType tail, NodeIndexType head) {
1750 DCHECK_GE(tail, 0);
1751 DCHECK_GE(head, 0);
1752 AddNode(tail > head ? tail : head);
1753
1754 // We inverse head and tail here because it is more convenient this way
1755 // during build time, see Build().
1756 head_.grow(head, tail);
1757 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
1758 return num_arcs_++;
1759}
1760
1761template <typename NodeIndexType, typename ArcIndexType>
1763 std::vector<ArcIndexType>* permutation) {
1764 DCHECK(!is_built_);
1765 if (is_built_) return;
1766 is_built_ = true;
1767 node_capacity_ = num_nodes_;
1768 arc_capacity_ = num_arcs_;
1769 this->FreezeCapacities();
1770 this->BuildStartAndForwardHead(&head_, &start_, permutation);
1771
1772 // Computes incoming degree of each nodes.
1773 reverse_start_.assign(num_nodes_, 0);
1774 for (int i = 0; i < num_arcs_; ++i) {
1775 reverse_start_[head_[i]]++;
1776 }
1777 this->ComputeCumulativeSum(&reverse_start_);
1778
1779 // Computes the reverse arcs of the forward arcs.
1780 // Note that this sort the reverse arcs with the same tail by head.
1781 opposite_.reserve(num_arcs_);
1782 for (int i = 0; i < num_arcs_; ++i) {
1783 // TODO(user): the 0 is wasted here, but minor optimisation.
1784 opposite_.grow(0, reverse_start_[head_[i]]++ - num_arcs_);
1785 }
1786
1787 // Computes in reverse_start_ the start index of the reverse arcs.
1788 for (int i = num_nodes_ - 1; i > 0; --i) {
1789 reverse_start_[i] = reverse_start_[i - 1] - num_arcs_;
1790 }
1791 if (num_nodes_ != 0) {
1792 reverse_start_[0] = -num_arcs_;
1793 }
1794
1795 // Fill reverse arc information.
1796 for (int i = 0; i < num_arcs_; ++i) {
1797 opposite_[opposite_[i]] = i;
1798 }
1799 for (const NodeIndexType node : Base::AllNodes()) {
1800 for (const ArcIndexType arc : OutgoingArcs(node)) {
1801 head_[opposite_[arc]] = node;
1802 }
1803 }
1804}
1805
1806template <typename NodeIndexType, typename ArcIndexType>
1807class ReverseArcStaticGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
1808 public:
1809 OutgoingArcIterator(const ReverseArcStaticGraph& graph, NodeIndexType node)
1810 : index_(graph.start_[node]), limit_(graph.DirectArcLimit(node)) {}
1811 OutgoingArcIterator(const ReverseArcStaticGraph& graph, NodeIndexType node,
1812 ArcIndexType arc)
1813 : index_(arc), limit_(graph.DirectArcLimit(node)) {
1814 DCHECK_GE(arc, graph.start_[node]);
1815 }
1816
1817 bool Ok() const { return index_ < limit_; }
1818 ArcIndexType Index() const { return index_; }
1819 void Next() {
1820 DCHECK(Ok());
1821 index_++;
1822 }
1823
1824 // TODO(user): we lose a bit by returning a BeginEndWrapper<> on top of this
1825 // iterator rather than a simple IntegerRange on the arc indices.
1827
1828 private:
1829 ArcIndexType index_;
1830 const ArcIndexType limit_;
1831};
1832
1833template <typename NodeIndexType, typename ArcIndexType>
1834class ReverseArcStaticGraph<NodeIndexType,
1835 ArcIndexType>::OppositeIncomingArcIterator {
1836 public:
1838 NodeIndexType node)
1839 : graph_(graph),
1840 limit_(graph.ReverseArcLimit(node)),
1841 index_(graph.reverse_start_[node]) {
1842 DCHECK(graph.IsNodeValid(node));
1843 DCHECK_LE(index_, limit_);
1844 }
1846 NodeIndexType node, ArcIndexType arc)
1847 : graph_(graph), limit_(graph.ReverseArcLimit(node)), index_(arc) {
1848 DCHECK(graph.IsNodeValid(node));
1849 DCHECK_GE(index_, graph.reverse_start_[node]);
1850 DCHECK_LE(index_, limit_);
1851 }
1852
1853 bool Ok() const { return index_ < limit_; }
1854 ArcIndexType Index() const { return index_; }
1855 void Next() {
1856 DCHECK(Ok());
1857 index_++;
1858 }
1859
1861
1862 protected:
1864 const ArcIndexType limit_;
1865 ArcIndexType index_;
1866};
1867
1868template <typename NodeIndexType, typename ArcIndexType>
1869class ReverseArcStaticGraph<NodeIndexType, ArcIndexType>::IncomingArcIterator
1871 public:
1872 IncomingArcIterator(const ReverseArcStaticGraph& graph, NodeIndexType node)
1873 : OppositeIncomingArcIterator(graph, node) {}
1874 IncomingArcIterator(const ReverseArcStaticGraph& graph, NodeIndexType node,
1875 ArcIndexType arc)
1876 : OppositeIncomingArcIterator(graph, node,
1877 arc == graph.ReverseArcLimit(node)
1878 ? graph.ReverseArcLimit(node)
1879 : graph.OppositeArc(arc)) {}
1880
1881 ArcIndexType Index() const {
1882 return this->index_ == this->limit_
1883 ? this->limit_
1884 : this->graph_.OppositeArc(this->index_);
1885 }
1886
1888};
1889
1890template <typename NodeIndexType, typename ArcIndexType>
1892 NodeIndexType, ArcIndexType>::OutgoingOrOppositeIncomingArcIterator {
1893 public:
1895 NodeIndexType node)
1896 : index_(graph.reverse_start_[node]),
1897 first_limit_(graph.ReverseArcLimit(node)),
1898 next_start_(graph.start_[node]),
1899 limit_(graph.DirectArcLimit(node)) {
1900 if (index_ == first_limit_) index_ = next_start_;
1901 DCHECK(graph.IsNodeValid(node));
1902 DCHECK((index_ < first_limit_) || (index_ >= next_start_));
1903 }
1905 NodeIndexType node, ArcIndexType arc)
1906 : index_(arc),
1907 first_limit_(graph.ReverseArcLimit(node)),
1908 next_start_(graph.start_[node]),
1909 limit_(graph.DirectArcLimit(node)) {
1910 DCHECK(graph.IsNodeValid(node));
1911 DCHECK((index_ >= graph.reverse_start_[node] && index_ < first_limit_) ||
1912 (index_ >= next_start_));
1913 }
1914
1915 ArcIndexType Index() const { return index_; }
1916 bool Ok() const { return index_ < limit_; }
1917 void Next() {
1918 DCHECK(Ok());
1919 index_++;
1920 if (index_ == first_limit_) {
1921 index_ = next_start_;
1922 }
1923 }
1924
1926
1927 private:
1928 ArcIndexType index_;
1929 const ArcIndexType first_limit_;
1930 const ArcIndexType next_start_;
1931 const ArcIndexType limit_;
1932};
1933
1934// ReverseArcMixedGraph implementation -----------------------------------------
1935
1937 DirectArcLimit(node));
1940 OutgoingOrOppositeIncoming,
1941 DirectArcLimit(node));
1943 Base::kNilArc);
1944
1945template <typename NodeIndexType, typename ArcIndexType>
1947 NodeIndexType node) const {
1948 return DirectArcLimit(node) - start_[node];
1949}
1950
1951template <typename NodeIndexType, typename ArcIndexType>
1953 NodeIndexType node) const {
1954 ArcIndexType degree(0);
1955 for (auto arc ABSL_ATTRIBUTE_UNUSED : OppositeIncomingArcs(node)) ++degree;
1956 return degree;
1957}
1958
1959template <typename NodeIndexType, typename ArcIndexType>
1962 NodeIndexType node) const {
1964 head_.data() + start_[node], head_.data() + DirectArcLimit(node));
1965}
1966
1967template <typename NodeIndexType, typename ArcIndexType>
1969 ArcIndexType arc) const {
1970 DCHECK(IsArcValid(arc));
1971 return ~arc;
1972}
1973
1974template <typename NodeIndexType, typename ArcIndexType>
1976 ArcIndexType arc) const {
1977 DCHECK(is_built_);
1978 DCHECK(IsArcValid(arc));
1979 return head_[arc];
1980}
1981
1982template <typename NodeIndexType, typename ArcIndexType>
1984 ArcIndexType arc) const {
1985 DCHECK(is_built_);
1986 return head_[OppositeArc(arc)];
1987}
1988
1989template <typename NodeIndexType, typename ArcIndexType>
1991 ArcIndexType bound) {
1992 Base::ReserveArcs(bound);
1993 if (bound <= num_arcs_) return;
1994 head_.reserve(bound);
1995}
1996
1997template <typename NodeIndexType, typename ArcIndexType>
1999 NodeIndexType node) {
2000 if (node < num_nodes_) return;
2001 DCHECK(!const_capacities_ || node < node_capacity_);
2002 num_nodes_ = node + 1;
2003}
2004
2005template <typename NodeIndexType, typename ArcIndexType>
2007 NodeIndexType tail, NodeIndexType head) {
2008 DCHECK_GE(tail, 0);
2009 DCHECK_GE(head, 0);
2010 AddNode(tail > head ? tail : head);
2011
2012 // We inverse head and tail here because it is more convenient this way
2013 // during build time, see Build().
2014 head_.grow(head, tail);
2015 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
2016 return num_arcs_++;
2017}
2018
2019template <typename NodeIndexType, typename ArcIndexType>
2021 std::vector<ArcIndexType>* permutation) {
2022 DCHECK(!is_built_);
2023 if (is_built_) return;
2024 is_built_ = true;
2025 node_capacity_ = num_nodes_;
2026 arc_capacity_ = num_arcs_;
2027 this->FreezeCapacities();
2028 this->BuildStartAndForwardHead(&head_, &start_, permutation);
2029
2030 // Fill tails.
2031 for (const NodeIndexType node : Base::AllNodes()) {
2032 for (const ArcIndexType arc : OutgoingArcs(node)) {
2033 head_[~arc] = node;
2034 }
2035 }
2036
2037 // Fill information for iterating over reverse arcs.
2038 reverse_start_.assign(num_nodes_, Base::kNilArc);
2039 next_.reserve(num_arcs_);
2040 for (const ArcIndexType arc : Base::AllForwardArcs()) {
2041 next_.push_back(reverse_start_[Head(arc)]);
2042 reverse_start_[Head(arc)] = -next_.size();
2043 }
2044}
2045
2046template <typename NodeIndexType, typename ArcIndexType>
2047class ReverseArcMixedGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
2048 public:
2049 OutgoingArcIterator(const ReverseArcMixedGraph& graph, NodeIndexType node)
2050 : index_(graph.start_[node]), limit_(graph.DirectArcLimit(node)) {}
2051 OutgoingArcIterator(const ReverseArcMixedGraph& graph, NodeIndexType node,
2052 ArcIndexType arc)
2053 : index_(arc), limit_(graph.DirectArcLimit(node)) {
2054 DCHECK_GE(arc, graph.start_[node]);
2055 }
2056
2057 bool Ok() const { return index_ < limit_; }
2058 ArcIndexType Index() const { return index_; }
2059 void Next() {
2060 DCHECK(Ok());
2061 index_++;
2062 }
2063
2064 // TODO(user): we lose a bit by returning a BeginEndWrapper<> on top of this
2065 // iterator rather than a simple IntegerRange on the arc indices.
2067
2068 private:
2069 ArcIndexType index_;
2070 const ArcIndexType limit_;
2071};
2072
2073template <typename NodeIndexType, typename ArcIndexType>
2074class ReverseArcMixedGraph<NodeIndexType,
2075 ArcIndexType>::OppositeIncomingArcIterator {
2076 public:
2078 NodeIndexType node)
2079 : graph_(&graph) {
2080 DCHECK(graph.is_built_);
2081 DCHECK(graph.IsNodeValid(node));
2082 index_ = graph.reverse_start_[node];
2083 }
2085 NodeIndexType node, ArcIndexType arc)
2086 : graph_(&graph), index_(arc) {
2087 DCHECK(graph.is_built_);
2088 DCHECK(graph.IsNodeValid(node));
2089 DCHECK(arc == Base::kNilArc || arc < 0);
2090 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
2091 }
2092 bool Ok() const { return index_ != Base::kNilArc; }
2093 ArcIndexType Index() const { return index_; }
2094 void Next() {
2095 DCHECK(Ok());
2096 index_ = graph_->next_[~index_];
2097 }
2098
2100
2101 protected:
2103 ArcIndexType index_;
2104};
2105
2106template <typename NodeIndexType, typename ArcIndexType>
2107class ReverseArcMixedGraph<NodeIndexType, ArcIndexType>::IncomingArcIterator
2109 public:
2110 IncomingArcIterator(const ReverseArcMixedGraph& graph, NodeIndexType node)
2111 : OppositeIncomingArcIterator(graph, node) {}
2112 IncomingArcIterator(const ReverseArcMixedGraph& graph, NodeIndexType node,
2113 ArcIndexType arc)
2115 graph, node, arc == Base::kNilArc ? arc : graph.OppositeArc(arc)) {}
2116 ArcIndexType Index() const {
2117 return this->index_ == Base::kNilArc
2119 : this->graph_->OppositeArc(this->index_);
2120 }
2121
2123};
2124
2125template <typename NodeIndexType, typename ArcIndexType>
2127 NodeIndexType, ArcIndexType>::OutgoingOrOppositeIncomingArcIterator {
2128 public:
2130 NodeIndexType node)
2131 : graph_(&graph) {
2132 limit_ = graph.DirectArcLimit(node); // also DCHECKs node and is_built_.
2133 index_ = graph.reverse_start_[node];
2134 restart_ = graph.start_[node];
2135 if (index_ == Base::kNilArc) {
2136 index_ = restart_;
2137 }
2138 }
2140 NodeIndexType node, ArcIndexType arc)
2141 : graph_(&graph) {
2142 limit_ = graph.DirectArcLimit(node);
2143 index_ = arc;
2144 restart_ = graph.start_[node];
2145 DCHECK(arc == Base::kNilArc || arc == limit_ || graph.Tail(arc) == node);
2146 }
2147 bool Ok() const {
2148 // Note that we always have limit_ <= Base::kNilArc.
2149 return index_ < limit_;
2150 }
2151 ArcIndexType Index() const { return index_; }
2152 void Next() {
2153 DCHECK(Ok());
2154 if (index_ < 0) {
2155 index_ = graph_->next_[graph_->OppositeArc(index_)];
2156 if (index_ == Base::kNilArc) {
2157 index_ = restart_;
2158 }
2159 } else {
2160 index_++;
2161 }
2162 }
2163
2165
2166 private:
2167 const ReverseArcMixedGraph* graph_;
2168 ArcIndexType index_;
2169 ArcIndexType restart_;
2170 ArcIndexType limit_;
2171};
2172
2173// CompleteGraph implementation ------------------------------------------------
2174// Nodes and arcs are implicit and not stored.
2175
2176template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
2177class CompleteGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
2179 using Base::arc_capacity_;
2182 using Base::num_arcs_;
2183 using Base::num_nodes_;
2184
2185 public:
2186 // Builds a complete graph with num_nodes nodes.
2187 explicit CompleteGraph(NodeIndexType num_nodes) {
2188 this->Reserve(num_nodes, num_nodes * num_nodes);
2189 this->FreezeCapacities();
2190 num_nodes_ = num_nodes;
2191 num_arcs_ = num_nodes * num_nodes;
2192 }
2193
2194 NodeIndexType Head(ArcIndexType arc) const;
2195 NodeIndexType Tail(ArcIndexType arc) const;
2196 ArcIndexType OutDegree(NodeIndexType node) const;
2197 IntegerRange<ArcIndexType> OutgoingArcs(NodeIndexType node) const;
2199 ArcIndexType from) const;
2200 IntegerRange<NodeIndexType> operator[](NodeIndexType node) const;
2201};
2202
2203template <typename NodeIndexType, typename ArcIndexType>
2205 ArcIndexType arc) const {
2206 DCHECK(this->IsArcValid(arc));
2207 return arc % num_nodes_;
2208}
2209
2210template <typename NodeIndexType, typename ArcIndexType>
2212 ArcIndexType arc) const {
2213 DCHECK(this->IsArcValid(arc));
2214 return arc / num_nodes_;
2215}
2216
2217template <typename NodeIndexType, typename ArcIndexType>
2219 NodeIndexType node) const {
2220 return num_nodes_;
2221}
2222
2223template <typename NodeIndexType, typename ArcIndexType>
2226 NodeIndexType node) const {
2227 DCHECK_LT(node, num_nodes_);
2229 static_cast<ArcIndexType>(num_nodes_) * node,
2230 static_cast<ArcIndexType>(num_nodes_) * (node + 1));
2231}
2232
2233template <typename NodeIndexType, typename ArcIndexType>
2236 NodeIndexType node, ArcIndexType from) const {
2237 DCHECK_LT(node, num_nodes_);
2239 from, static_cast<ArcIndexType>(num_nodes_) * (node + 1));
2240}
2241
2242template <typename NodeIndexType, typename ArcIndexType>
2245 NodeIndexType node) const {
2246 DCHECK_LT(node, num_nodes_);
2247 return IntegerRange<NodeIndexType>(0, num_nodes_);
2248}
2249
2250// CompleteBipartiteGraph implementation ---------------------------------------
2251// Nodes and arcs are implicit and not stored.
2252
2253template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
2255 : public BaseGraph<NodeIndexType, ArcIndexType, false> {
2257 using Base::arc_capacity_;
2260 using Base::num_arcs_;
2261 using Base::num_nodes_;
2262
2263 public:
2264 // Builds a complete bipartite graph from a set of left nodes to a set of
2265 // right nodes.
2266 // Indices of left nodes of the bipartite graph range from 0 to left_nodes-1;
2267 // indices of right nodes range from left_nodes to left_nodes+right_nodes-1.
2268 CompleteBipartiteGraph(NodeIndexType left_nodes, NodeIndexType right_nodes)
2269 : left_nodes_(left_nodes), right_nodes_(right_nodes) {
2270 this->Reserve(left_nodes + right_nodes, left_nodes * right_nodes);
2271 this->FreezeCapacities();
2272 num_nodes_ = left_nodes + right_nodes;
2273 num_arcs_ = left_nodes * right_nodes;
2274 }
2275
2276 NodeIndexType Head(ArcIndexType arc) const;
2277 NodeIndexType Tail(ArcIndexType arc) const;
2278 ArcIndexType OutDegree(NodeIndexType node) const;
2279 IntegerRange<ArcIndexType> OutgoingArcs(NodeIndexType node) const;
2281 ArcIndexType from) const;
2282 IntegerRange<NodeIndexType> operator[](NodeIndexType node) const;
2283
2284 // Deprecated interface.
2286 public:
2287 OutgoingArcIterator(const CompleteBipartiteGraph& graph, NodeIndexType node)
2288 : index_(graph.right_nodes_ * node),
2289 limit_(node >= graph.left_nodes_ ? index_
2290 : graph.right_nodes_ * (node + 1)) {}
2291
2292 bool Ok() const { return index_ < limit_; }
2293 ArcIndexType Index() const { return index_; }
2294 void Next() { index_++; }
2295
2296 private:
2297 ArcIndexType index_;
2298 const ArcIndexType limit_;
2299 };
2300
2301 private:
2302 const NodeIndexType left_nodes_;
2303 const NodeIndexType right_nodes_;
2304};
2305
2306template <typename NodeIndexType, typename ArcIndexType>
2308 ArcIndexType arc) const {
2309 DCHECK(this->IsArcValid(arc));
2310 return left_nodes_ + arc % right_nodes_;
2311}
2312
2313template <typename NodeIndexType, typename ArcIndexType>
2315 ArcIndexType arc) const {
2316 DCHECK(this->IsArcValid(arc));
2317 return arc / right_nodes_;
2318}
2319
2320template <typename NodeIndexType, typename ArcIndexType>
2322 NodeIndexType node) const {
2323 return (node < left_nodes_) ? right_nodes_ : 0;
2324}
2325
2326template <typename NodeIndexType, typename ArcIndexType>
2329 NodeIndexType node) const {
2330 if (node < left_nodes_) {
2331 return IntegerRange<ArcIndexType>(right_nodes_ * node,
2332 right_nodes_ * (node + 1));
2333 } else {
2334 return IntegerRange<ArcIndexType>(0, 0);
2335 }
2336}
2337
2338template <typename NodeIndexType, typename ArcIndexType>
2341 NodeIndexType node, ArcIndexType from) const {
2342 if (node < left_nodes_) {
2343 return IntegerRange<ArcIndexType>(from, right_nodes_ * (node + 1));
2344 } else {
2345 return IntegerRange<ArcIndexType>(0, 0);
2346 }
2347}
2348
2349template <typename NodeIndexType, typename ArcIndexType>
2352 NodeIndexType node) const {
2353 if (node < left_nodes_) {
2354 return IntegerRange<NodeIndexType>(left_nodes_, left_nodes_ + right_nodes_);
2355 } else {
2356 return IntegerRange<NodeIndexType>(0, 0);
2357 }
2358}
2359
2360// Defining the simplest Graph interface as Graph for convenience.
2362
2363} // namespace util
2364
2365#undef DEFINE_RANGE_BASED_ARC_ITERATION
2366#undef DEFINE_STL_ITERATOR_FUNCTIONS
2367
2368#endif // UTIL_GRAPH_GRAPH_H_
int64_t max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
#define CHECK(condition)
Definition: base/logging.h:491
#define DCHECK_LE(val1, val2)
Definition: base/logging.h:888
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:698
#define DCHECK_GE(val1, val2)
Definition: base/logging.h:890
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:889
#define LOG(severity)
Definition: base/logging.h:416
#define DCHECK(condition)
Definition: base/logging.h:885
ArcIndexType arc_capacity_
Definition: graph.h:281
static const NodeIndexType kNilNode
Definition: graph.h:260
IntegerRange< ArcIndex > AllForwardArcs() const
Definition: graph.h:942
void GroupForwardArcsByFunctor(const A &a, B *b)
Definition: graph.h:266
void FreezeCapacities()
Definition: graph.h:973
bool IsNodeValid(NodeIndexType node) const
Definition: graph.h:215
virtual void ReserveArcs(ArcIndexType bound)
Definition: graph.h:243
void Reserve(NodeIndexType node_capacity, ArcIndexType arc_capacity)
Definition: graph.h:249
NodeIndexType node_capacity_
Definition: graph.h:279
ArcIndexType num_arcs() const
Definition: graph.h:206
void BuildStartAndForwardHead(SVector< NodeIndexType > *head, std::vector< ArcIndexType > *start, std::vector< ArcIndexType > *permutation)
Definition: graph.h:1002
NodeIndexType num_nodes() const
Definition: graph.h:203
ArcIndexType arc_capacity() const
Definition: graph.h:966
IntegerRange< NodeIndex > AllNodes() const
Definition: graph.h:936
bool const_capacities_
Definition: graph.h:282
ArcIndexType ArcIndex
Definition: graph.h:192
NodeIndexType num_nodes_
Definition: graph.h:278
static const ArcIndexType kNilArc
Definition: graph.h:261
void ComputeCumulativeSum(std::vector< ArcIndexType > *v)
Definition: graph.h:985
ArcIndexType max_end_arc_index() const
Definition: graph.h:269
virtual ~BaseGraph()
Definition: graph.h:200
NodeIndexType node_capacity() const
Definition: graph.h:958
bool IsArcValid(ArcIndexType arc) const
Definition: graph.h:221
NodeIndexType NodeIndex
Definition: graph.h:191
ArcIndexType num_arcs_
Definition: graph.h:280
virtual void ReserveNodes(NodeIndexType bound)
Definition: graph.h:237
OutgoingArcIterator(const CompleteBipartiteGraph &graph, NodeIndexType node)
Definition: graph.h:2287
IntegerRange< ArcIndexType > OutgoingArcs(NodeIndexType node) const
Definition: graph.h:2328
NodeIndexType Tail(ArcIndexType arc) const
Definition: graph.h:2314
ArcIndexType OutDegree(NodeIndexType node) const
Definition: graph.h:2321
CompleteBipartiteGraph(NodeIndexType left_nodes, NodeIndexType right_nodes)
Definition: graph.h:2268
IntegerRange< NodeIndexType > operator[](NodeIndexType node) const
Definition: graph.h:2351
IntegerRange< ArcIndexType > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
Definition: graph.h:2340
NodeIndexType Head(ArcIndexType arc) const
Definition: graph.h:2307
IntegerRange< ArcIndexType > OutgoingArcs(NodeIndexType node) const
Definition: graph.h:2225
NodeIndexType Tail(ArcIndexType arc) const
Definition: graph.h:2211
CompleteGraph(NodeIndexType num_nodes)
Definition: graph.h:2187
ArcIndexType OutDegree(NodeIndexType node) const
Definition: graph.h:2218
IntegerRange< NodeIndexType > operator[](NodeIndexType node) const
Definition: graph.h:2244
IntegerRange< ArcIndexType > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
Definition: graph.h:2235
NodeIndexType Head(ArcIndexType arc) const
Definition: graph.h:2204
DEFINE_STL_ITERATOR_FUNCTIONS(OutgoingArcIterator)
OutgoingArcIterator(const ListGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:1185
OutgoingArcIterator(const ListGraph &graph, NodeIndexType node)
Definition: graph.h:1181
ArcIndexType Index() const
Definition: graph.h:1192
const NodeIndexType * pointer
Definition: graph.h:1210
NodeIndexType Index() const
Definition: graph.h:1225
const NodeIndexType & reference
Definition: graph.h:1211
bool operator!=(const typename ListGraph< NodeIndexType, ArcIndexType >::OutgoingHeadIterator &other) const
Definition: graph.h:1231
NodeIndexType operator*() const
Definition: graph.h:1236
std::input_iterator_tag iterator_category
Definition: graph.h:1208
OutgoingHeadIterator(const ListGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:1218
OutgoingHeadIterator(const ListGraph &graph, NodeIndexType node)
Definition: graph.h:1214
BeginEndWrapper< OutgoingHeadIterator > operator[](NodeIndexType node) const
Definition: graph.h:1104
ListGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
Definition: graph.h:314
NodeIndexType Tail(ArcIndexType arc) const
Definition: graph.h:1111
void ReserveArcs(ArcIndexType bound) override
Definition: graph.h:1162
void ReserveNodes(NodeIndexType bound) override
Definition: graph.h:1155
void Build()
Definition: graph.h:341
void AddNode(NodeIndexType node)
Definition: graph.h:1133
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition: graph.h:1141
ArcIndexType OutDegree(NodeIndexType node) const
Definition: graph.h:1125
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
NodeIndexType Head(ArcIndexType arc) const
Definition: graph.h:1118
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
IncomingArcIterator(const ReverseArcListGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:1593
IncomingArcIterator(const ReverseArcListGraph &graph, NodeIndexType node)
Definition: graph.h:1591
OppositeIncomingArcIterator(const ReverseArcListGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:1565
DEFINE_STL_ITERATOR_FUNCTIONS(OppositeIncomingArcIterator)
OppositeIncomingArcIterator(const ReverseArcListGraph &graph, NodeIndexType node)
Definition: graph.h:1560
OutgoingArcIterator(const ReverseArcListGraph &graph, NodeIndexType node)
Definition: graph.h:1531
OutgoingArcIterator(const ReverseArcListGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:1535
OutgoingHeadIterator(const ReverseArcListGraph &graph, NodeIndexType node)
Definition: graph.h:1651
OutgoingHeadIterator(const ReverseArcListGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:1655
OutgoingOrOppositeIncomingArcIterator(const ReverseArcListGraph &graph, NodeIndexType node)
Definition: graph.h:1613
DEFINE_STL_ITERATOR_FUNCTIONS(OutgoingOrOppositeIncomingArcIterator)
OutgoingOrOppositeIncomingArcIterator(const ReverseArcListGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:1619
ArcIndexType OppositeArc(ArcIndexType arc) const
Definition: graph.h:1459
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcs(NodeIndexType node) const
BeginEndWrapper< IncomingArcIterator > IncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
NodeIndexType Tail(ArcIndexType arc) const
Definition: graph.h:1473
BeginEndWrapper< IncomingArcIterator > IncomingArcs(NodeIndexType node) const
void ReserveArcs(ArcIndexType bound) override
Definition: graph.h:1488
void ReserveNodes(NodeIndexType bound) override
Definition: graph.h:1479
ArcIndexType InDegree(NodeIndexType node) const
Definition: graph.h:1451
void AddNode(NodeIndexType node)
Definition: graph.h:1497
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition: graph.h:1507
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcs(NodeIndexType node) const
ReverseArcListGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
Definition: graph.h:473
ArcIndexType OutDegree(NodeIndexType node) const
Definition: graph.h:1443
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
NodeIndexType Head(ArcIndexType arc) const
Definition: graph.h:1466
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
BeginEndWrapper< OutgoingHeadIterator > operator[](NodeIndexType node) const
Definition: graph.h:1435
IncomingArcIterator(const ReverseArcMixedGraph &graph, NodeIndexType node)
Definition: graph.h:2110
IncomingArcIterator(const ReverseArcMixedGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:2112
DEFINE_STL_ITERATOR_FUNCTIONS(OppositeIncomingArcIterator)
OppositeIncomingArcIterator(const ReverseArcMixedGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:2084
OppositeIncomingArcIterator(const ReverseArcMixedGraph &graph, NodeIndexType node)
Definition: graph.h:2077
OutgoingArcIterator(const ReverseArcMixedGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:2051
OutgoingArcIterator(const ReverseArcMixedGraph &graph, NodeIndexType node)
Definition: graph.h:2049
OutgoingOrOppositeIncomingArcIterator(const ReverseArcMixedGraph &graph, NodeIndexType node)
Definition: graph.h:2129
OutgoingOrOppositeIncomingArcIterator(const ReverseArcMixedGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:2139
DEFINE_STL_ITERATOR_FUNCTIONS(OutgoingOrOppositeIncomingArcIterator)
ArcIndexType OppositeArc(ArcIndexType arc) const
Definition: graph.h:1968
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcs(NodeIndexType node) const
BeginEndWrapper< IncomingArcIterator > IncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
NodeIndexType Tail(ArcIndexType arc) const
Definition: graph.h:1983
BeginEndWrapper< IncomingArcIterator > IncomingArcs(NodeIndexType node) const
void ReserveArcs(ArcIndexType bound) override
Definition: graph.h:1990
ArcIndexType InDegree(NodeIndexType node) const
Definition: graph.h:1952
void AddNode(NodeIndexType node)
Definition: graph.h:1998
BeginEndWrapper< NodeIndexType const * > operator[](NodeIndexType node) const
Definition: graph.h:1961
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition: graph.h:2006
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcs(NodeIndexType node) const
ArcIndexType OutDegree(NodeIndexType node) const
Definition: graph.h:1946
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
NodeIndexType Head(ArcIndexType arc) const
Definition: graph.h:1975
ReverseArcMixedGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
Definition: graph.h:649
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
IncomingArcIterator(const ReverseArcStaticGraph &graph, NodeIndexType node)
Definition: graph.h:1872
IncomingArcIterator(const ReverseArcStaticGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:1874
OppositeIncomingArcIterator(const ReverseArcStaticGraph &graph, NodeIndexType node)
Definition: graph.h:1837
OppositeIncomingArcIterator(const ReverseArcStaticGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:1845
DEFINE_STL_ITERATOR_FUNCTIONS(OppositeIncomingArcIterator)
OutgoingArcIterator(const ReverseArcStaticGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:1811
OutgoingArcIterator(const ReverseArcStaticGraph &graph, NodeIndexType node)
Definition: graph.h:1809
OutgoingOrOppositeIncomingArcIterator(const ReverseArcStaticGraph &graph, NodeIndexType node)
Definition: graph.h:1894
DEFINE_STL_ITERATOR_FUNCTIONS(OutgoingOrOppositeIncomingArcIterator)
OutgoingOrOppositeIncomingArcIterator(const ReverseArcStaticGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:1904
ArcIndexType OppositeArc(ArcIndexType arc) const
Definition: graph.h:1709
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcs(NodeIndexType node) const
BeginEndWrapper< IncomingArcIterator > IncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
NodeIndexType Tail(ArcIndexType arc) const
Definition: graph.h:1725
BeginEndWrapper< IncomingArcIterator > IncomingArcs(NodeIndexType node) const
ReverseArcStaticGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
Definition: graph.h:561
void ReserveArcs(ArcIndexType bound) override
Definition: graph.h:1732
ArcIndexType InDegree(NodeIndexType node) const
Definition: graph.h:1695
void AddNode(NodeIndexType node)
Definition: graph.h:1740
BeginEndWrapper< NodeIndexType const * > operator[](NodeIndexType node) const
Definition: graph.h:1702
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition: graph.h:1748
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcs(NodeIndexType node) const
ArcIndexType OutDegree(NodeIndexType node) const
Definition: graph.h:1689
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
NodeIndexType Head(ArcIndexType arc) const
Definition: graph.h:1717
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
T * data() const
Definition: graph.h:844
SVector(const SVector &other)
Definition: graph.h:781
SVector & operator=(SVector &&other)
Definition: graph.h:804
SVector(SVector &&other)
Definition: graph.h:803
T & operator[](int n)
Definition: graph.h:813
void resize(int n)
Definition: graph.h:825
void clear_and_dealloc()
Definition: graph.h:898
SVector & operator=(const SVector &other)
Definition: graph.h:782
void reserve(int n)
Definition: graph.h:852
void grow(const T &left=T(), const T &right=T())
Definition: graph.h:875
void clear()
Definition: graph.h:842
int capacity() const
Definition: graph.h:894
const T & operator[](int n) const
Definition: graph.h:819
void swap(SVector< T > &x)
Definition: graph.h:846
int max_size() const
Definition: graph.h:896
int size() const
Definition: graph.h:892
OutgoingArcIterator(const StaticGraph &graph, NodeIndexType node, ArcIndexType arc)
Definition: graph.h:1396
DEFINE_STL_ITERATOR_FUNCTIONS(OutgoingArcIterator)
OutgoingArcIterator(const StaticGraph &graph, NodeIndexType node)
Definition: graph.h:1394
ArcIndexType Index() const
Definition: graph.h:1403
NodeIndexType Tail(ArcIndexType arc) const
Definition: graph.h:1307
void ReserveArcs(ArcIndexType bound) override
Definition: graph.h:1270
void ReserveNodes(NodeIndexType bound) override
Definition: graph.h:1262
void Build()
Definition: graph.h:436
void AddNode(NodeIndexType node)
Definition: graph.h:1278
BeginEndWrapper< NodeIndexType const * > operator[](NodeIndexType node) const
Definition: graph.h:1250
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition: graph.h:1286
StaticGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
Definition: graph.h:409
ArcIndexType OutDegree(NodeIndexType node) const
Definition: graph.h:1256
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
NodeIndexType Head(ArcIndexType arc) const
Definition: graph.h:1314
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
int64_t b
int64_t a
const int64_t limit_
const int FATAL
Definition: log_severity.h:32
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
Definition: id_map.h:263
ListGraph Graph
Definition: graph.h:2361
DEFINE_RANGE_BASED_ARC_ITERATION(ListGraph, Outgoing, Base::kNilArc)
void Permute(const IntVector &permutation, Array *array_to_permute)
Definition: graph.h:739
void PermuteWithExplicitElementType(const IntVector &permutation, Array *array_to_permute, ElementType unused)
Definition: graph.h:726
void * malloc(YYSIZE_T)
void free(void *)
int64_t delta
Definition: resource.cc:1692
int64_t bound
int64_t tail
int64_t head