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