C++ Reference

C++ Reference: Graph

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