154#ifndef UTIL_GRAPH_GRAPH_H_
155#define UTIL_GRAPH_GRAPH_H_
165#include <type_traits>
168#include "absl/base/port.h"
169#include "absl/debugging/leak_check.h"
170#include "absl/types/span.h"
188template <
typename NodeIndexType = int32_t,
typename ArcIndexType = int32_t,
189 bool HasReverseArcs =
false>
274 template <
typename A,
typename B>
276 LOG(FATAL) <<
"Not supported";
284 std::vector<ArcIndexType>*
start,
285 std::vector<ArcIndexType>* permutation);
308template <
typename NodeIndexType =
int32_t,
typename ArcIndexType =
int32_t>
333 void AddNode(NodeIndexType node);
352 void Build(std::vector<ArcIndexType>* permutation);
355 class OutgoingArcIterator;
356 class OutgoingHeadIterator;
363 ArcIndexType
OutDegree(NodeIndexType node)
const;
373 NodeIndexType node, ArcIndexType from)
const;
381 NodeIndexType
Tail(ArcIndexType
arc)
const;
382 NodeIndexType
Head(ArcIndexType
arc)
const;
388 std::vector<ArcIndexType> start_;
389 std::vector<ArcIndexType> next_;
390 std::vector<NodeIndexType> head_;
391 std::vector<NodeIndexType> tail_;
407template <
typename NodeIndexType =
int32_t,
typename ArcIndexType =
int32_t>
418 StaticGraph() : is_built_(false), arc_in_order_(true), last_tail_seen_(0) {}
420 : is_built_(false), arc_in_order_(true), last_tail_seen_(0) {
427 template <
class ArcContainer>
429 const ArcContainer& arcs);
434 NodeIndexType
Head(ArcIndexType
arc)
const;
435 NodeIndexType
Tail(ArcIndexType
arc)
const;
436 ArcIndexType
OutDegree(NodeIndexType node)
const;
439 NodeIndexType node, ArcIndexType from)
const;
444 absl::Span<const NodeIndexType>
operator[](NodeIndexType node)
const;
448 void AddNode(NodeIndexType node);
452 void Build(std::vector<ArcIndexType>* permutation);
455 ArcIndexType DirectArcLimit(NodeIndexType node)
const {
458 return node + 1 < num_nodes_ ? start_[node + 1] : num_arcs_;
463 NodeIndexType last_tail_seen_;
464 std::vector<ArcIndexType> start_;
465 std::vector<NodeIndexType> head_;
466 std::vector<NodeIndexType> tail_;
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");
501 class OutgoingOrOppositeIncomingArcIterator;
502 class OppositeIncomingArcIterator;
503 class IncomingArcIterator;
504 class OutgoingArcIterator;
505 class OutgoingHeadIterator;
508 ArcIndexType
OutDegree(NodeIndexType node)
const;
509 ArcIndexType
InDegree(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;
538 NodeIndexType
Head(ArcIndexType
arc)
const;
539 NodeIndexType
Tail(ArcIndexType
arc)
const;
543 void AddNode(NodeIndexType node);
547 void Build(std::vector<ArcIndexType>* permutation);
550 std::vector<ArcIndexType> start_;
551 std::vector<ArcIndexType> reverse_start_;
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");
588 class OutgoingOrOppositeIncomingArcIterator;
589 class OppositeIncomingArcIterator;
590 class IncomingArcIterator;
591 class OutgoingArcIterator;
594 ArcIndexType
OutDegree(NodeIndexType node)
const;
595 ArcIndexType
InDegree(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;
616 absl::Span<const NodeIndexType>
operator[](NodeIndexType node)
const;
620 NodeIndexType
Head(ArcIndexType
arc)
const;
621 NodeIndexType
Tail(ArcIndexType
arc)
const;
624 void AddNode(NodeIndexType node);
628 void Build(std::vector<ArcIndexType>* permutation);
631 ArcIndexType DirectArcLimit(NodeIndexType node)
const {
634 return node + 1 < num_nodes_ ? start_[node + 1] : num_arcs_;
636 ArcIndexType ReverseArcLimit(NodeIndexType node)
const {
639 return node + 1 < num_nodes_ ? reverse_start_[node + 1] : 0;
643 std::vector<ArcIndexType> start_;
644 std::vector<ArcIndexType> reverse_start_;
645 SVector<NodeIndexType> head_;
646 SVector<ArcIndexType> opposite_;
655template <
typename NodeIndexType =
int32_t,
typename ArcIndexType =
int32_t>
657 :
public BaseGraph<NodeIndexType, ArcIndexType, true> {
676 class OutgoingOrOppositeIncomingArcIterator;
677 class OppositeIncomingArcIterator;
678 class IncomingArcIterator;
679 class OutgoingArcIterator;
681 ArcIndexType
OutDegree(NodeIndexType node)
const;
682 ArcIndexType
InDegree(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;
703 absl::Span<const NodeIndexType>
operator[](NodeIndexType node)
const;
707 NodeIndexType
Head(ArcIndexType
arc)
const;
708 NodeIndexType
Tail(ArcIndexType
arc)
const;
711 void AddNode(NodeIndexType node);
715 void Build(std::vector<ArcIndexType>* permutation);
718 ArcIndexType DirectArcLimit(NodeIndexType node)
const {
721 return node + 1 < num_nodes_ ? start_[node + 1] : num_arcs_;
725 std::vector<ArcIndexType> start_;
726 std::vector<ArcIndexType> reverse_start_;
727 std::vector<ArcIndexType> next_;
728 SVector<NodeIndexType> head_;
744template <
class IntVector,
class Array,
class ElementType>
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];
752 for (
size_t i = 0; i < permutation.size(); ++i) {
753 (*array_to_permute)[permutation[i]] = temp[i];
757template <
class IntVector,
class Array>
758void Permute(
const IntVector& permutation, Array* array_to_permute) {
759 if (permutation.empty()) {
763 (*array_to_permute)[0]);
768template <
class IntVector>
770 std::vector<bool>* array_to_permute) {
771 if (permutation.empty()) {
795 SVector() : base_(nullptr), size_(0), capacity_(0) {}
802 if (capacity_ < other.size_) {
806 capacity_ = other.size_;
807 base_ = Allocate(capacity_);
808 CHECK(base_ !=
nullptr);
815 CopyInternal(other, std::is_integral<T>());
832 DCHECK_GE(n, -size_);
838 DCHECK_GE(n, -size_);
844 for (
int i = -n; i < -size_; ++i) {
847 for (
int i = size_; i < n; ++i) {
850 for (
int i = -size_; i < -n; ++i) {
853 for (
int i = n; i < size_; ++i) {
861 T*
data()
const {
return base_; }
864 std::swap(base_,
x.base_);
865 std::swap(size_,
x.size_);
866 std::swap(capacity_,
x.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;
879 for (
int i = -size_; i < size_; ++i) {
880 new (new_base + i) T(std::move(base_[i]));
882 int saved_size = size_;
886 capacity_ = new_capacity;
892 void grow(
const T& left = T(),
const T& right = T()) {
893 if (size_ == capacity_) {
899 new (base_ + size_) T(right_copy);
900 new (base_ - size_ - 1) T(left_copy);
903 new (base_ + size_) T(right);
904 new (base_ - size_ - 1) T(left);
909 int size()
const {
return size_; }
913 int max_size()
const {
return std::numeric_limits<int>::max(); }
916 if (base_ ==
nullptr)
return;
919 free(base_ - capacity_);
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));
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]);
943 return absl::IgnoreLeak(
947 int NewCapacity(
int delta) {
949 double candidate = 1.3 *
static_cast<double>(capacity_);
950 if (candidate >
static_cast<double>(
max_size())) {
951 candidate =
static_cast<double>(
max_size());
953 int new_capacity =
static_cast<int>(candidate);
954 if (new_capacity > capacity_ +
delta) {
957 return capacity_ +
delta;
967template <
typename NodeIndexType,
typename ArcIndexType,
bool HasReverseArcs>
968IntegerRange<NodeIndexType>
973template <
typename NodeIndexType,
typename ArcIndexType,
bool HasReverseArcs>
979template <
typename NodeIndexType,
typename ArcIndexType,
bool HasReverseArcs>
982 std::numeric_limits<NodeIndexType>::max();
984template <
typename NodeIndexType,
typename ArcIndexType,
bool HasReverseArcs>
987 std::numeric_limits<ArcIndexType>::max();
989template <
typename NodeIndexType,
typename ArcIndexType,
bool HasReverseArcs>
994 return node_capacity_ > num_nodes_ ? node_capacity_ : num_nodes_;
997template <
typename NodeIndexType,
typename ArcIndexType,
bool HasReverseArcs>
1001 return arc_capacity_ > num_arcs_ ? arc_capacity_ : num_arcs_;
1004template <
typename NodeIndexType,
typename ArcIndexType,
bool HasReverseArcs>
1005void BaseGraph<NodeIndexType, ArcIndexType,
1006 HasReverseArcs>::FreezeCapacities() {
1009 const_capacities_ =
true;
1010 node_capacity_ = std::max(node_capacity_, num_nodes_);
1011 arc_capacity_ = std::max(arc_capacity_, num_arcs_);
1016template <
typename NodeIndexType,
typename ArcIndexType,
bool HasReverseArcs>
1019 ArcIndexType sum = 0;
1020 for (
int i = 0; i < num_nodes_; ++i) {
1021 ArcIndexType temp = (*v)[i];
1025 DCHECK(sum == num_arcs_);
1033template <
typename NodeIndexType,
typename ArcIndexType,
bool HasReverseArcs>
1036 std::vector<ArcIndexType>*
start,
1037 std::vector<ArcIndexType>* permutation) {
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;
1052 ComputeCumulativeSum(
start);
1056 if (!permutation_needed) {
1057 for (
int i = 0; i < num_arcs_; ++i) {
1058 (*head)[i] = (*head)[~i];
1060 if (permutation !=
nullptr) {
1061 permutation->clear();
1068 std::vector<ArcIndexType> perm(num_arcs_);
1069 for (
int i = 0; i < num_arcs_; ++i) {
1070 perm[i] = (*start)[(*head)[i]]++;
1074 for (
int i = num_nodes_ - 1; i > 0; --i) {
1075 (*start)[i] = (*start)[i - 1];
1081 for (
int i = 0; i < num_arcs_; ++i) {
1082 (*head)[perm[i]] = (*head)[~i];
1084 if (permutation !=
nullptr) {
1085 permutation->swap(perm);
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)); \
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)); \
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_; \
1124 bool operator==(const iterator_class_name& other) const { \
1125 return this->index_ == other.index_; \
1127 ArcIndexType operator*() const { return this->Index(); } \
1128 void operator++() { this->Next(); }
1134template <
typename NodeIndexType,
typename ArcIndexType>
1143template <
typename NodeIndexType,
typename ArcIndexType>
1145 ArcIndexType
arc)
const {
1150template <
typename NodeIndexType,
typename ArcIndexType>
1152 ArcIndexType
arc)
const {
1157template <
typename NodeIndexType,
typename ArcIndexType>
1159 NodeIndexType node)
const {
1160 ArcIndexType degree(0);
1161 for (
auto arc ABSL_ATTRIBUTE_UNUSED : OutgoingArcs(node)) ++degree;
1165template <
typename NodeIndexType,
typename ArcIndexType>
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);
1173template <
typename NodeIndexType,
typename ArcIndexType>
1175 NodeIndexType
tail, NodeIndexType
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_);
1187template <
typename NodeIndexType,
typename ArcIndexType>
1189 Base::ReserveNodes(
bound);
1191 start_.reserve(
bound);
1194template <
typename NodeIndexType,
typename ArcIndexType>
1196 Base::ReserveArcs(
bound);
1198 head_.reserve(
bound);
1199 tail_.reserve(
bound);
1200 next_.reserve(
bound);
1203template <
typename NodeIndexType,
typename ArcIndexType>
1205 std::vector<ArcIndexType>* permutation) {
1206 if (permutation !=
nullptr) {
1207 permutation->clear();
1211template <
typename NodeIndexType,
typename ArcIndexType>
1212class ListGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
1215 : graph_(
graph), index_(
graph.start_[node]) {
1221 DCHECK(
graph.IsNodeValid(node));
1225 ArcIndexType Index()
const {
return index_; }
1228 index_ = graph_.next_[index_];
1235 ArcIndexType index_;
1238template <
typename NodeIndexType,
typename ArcIndexType>
1248 : graph_(
graph), index_(
graph.start_[node]) {
1254 DCHECK(
graph.IsNodeValid(node));
1258 NodeIndexType Index()
const {
return graph_.Head(index_); }
1261 index_ = graph_.next_[index_];
1266 NodeIndexType, ArcIndexType>::OutgoingHeadIterator& other)
const {
1267 return index_ != other.index_;
1269 NodeIndexType operator*()
const {
return Index(); }
1270 void operator++() {
Next(); }
1274 ArcIndexType index_;
1279template <
typename NodeIndexType,
typename ArcIndexType>
1280template <
class ArcContainer>
1283 const ArcContainer& arcs) {
1285 for (
const auto& [from,
to] : arcs) g.AddArc(from,
to);
1292template <
typename NodeIndexType,
typename ArcIndexType>
1293absl::Span<const NodeIndexType>
1295 return absl::Span<const NodeIndexType>(head_.data() + start_[node],
1296 DirectArcLimit(node) - start_[node]);
1299template <
typename NodeIndexType,
typename ArcIndexType>
1301 NodeIndexType node)
const {
1302 return DirectArcLimit(node) - start_[node];
1305template <
typename NodeIndexType,
typename ArcIndexType>
1307 NodeIndexType
bound) {
1309 if (
bound <= num_nodes_)
return;
1310 start_.reserve(
bound);
1313template <
typename NodeIndexType,
typename ArcIndexType>
1315 Base::ReserveArcs(
bound);
1317 head_.reserve(
bound);
1318 tail_.reserve(
bound);
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);
1329template <
typename NodeIndexType,
typename ArcIndexType>
1331 NodeIndexType
tail, NodeIndexType
head) {
1336 if (arc_in_order_) {
1337 if (
tail >= last_tail_seen_) {
1339 last_tail_seen_ =
tail;
1341 arc_in_order_ =
false;
1344 tail_.push_back(
tail);
1345 head_.push_back(
head);
1346 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
1350template <
typename NodeIndexType,
typename ArcIndexType>
1352 ArcIndexType
arc)
const {
1357template <
typename NodeIndexType,
typename ArcIndexType>
1359 ArcIndexType
arc)
const {
1376template <
typename NodeIndexType,
typename ArcIndexType>
1378 std::vector<ArcIndexType>* permutation) {
1380 if (is_built_)
return;
1382 node_capacity_ = num_nodes_;
1383 arc_capacity_ = num_arcs_;
1384 this->FreezeCapacities();
1387 if (arc_in_order_) {
1388 if (permutation !=
nullptr) {
1389 permutation->clear();
1391 this->ComputeCumulativeSum(&start_);
1397 start_.assign(num_nodes_, 0);
1398 for (
int i = 0; i < num_arcs_; ++i) {
1401 this->ComputeCumulativeSum(&start_);
1405 std::vector<ArcIndexType> perm(num_arcs_);
1406 for (
int i = 0;
i < num_arcs_; ++
i) {
1407 perm[
i] = start_[tail_[
i]]++;
1411 CHECK_EQ(tail_.size(),
static_cast<size_t>(num_arcs_));
1413 for (
int i = 0;
i < num_arcs_; ++
i) {
1414 head_[perm[
i]] = tail_[
i];
1417 if (permutation !=
nullptr) {
1418 permutation->swap(perm);
1422 for (
int i = num_nodes_ - 1;
i > 0; --
i) {
1423 start_[
i] = start_[
i - 1];
1428 for (
const NodeIndexType node : Base::AllNodes()) {
1429 for (
const ArcIndexType
arc : OutgoingArcs(node)) {
1435template <
typename NodeIndexType,
typename ArcIndexType>
1436class StaticGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
1443 DCHECK_GE(
arc,
graph.start_[node]);
1446 bool Ok()
const {
return index_ <
limit_; }
1447 ArcIndexType Index()
const {
return index_; }
1463 ArcIndexType index_;
1464 const ArcIndexType
limit_;
1472 OutgoingOrOppositeIncoming, Base::kNilArc);
1476template <
typename NodeIndexType,
typename ArcIndexType>
1478 NodeIndexType, ArcIndexType>::OutgoingHeadIterator>
1480 NodeIndexType node)
const {
1486template <
typename NodeIndexType,
typename ArcIndexType>
1488 NodeIndexType node)
const {
1489 ArcIndexType degree(0);
1490 for (
auto arc ABSL_ATTRIBUTE_UNUSED : OutgoingArcs(node)) ++degree;
1494template <
typename NodeIndexType,
typename ArcIndexType>
1496 NodeIndexType node)
const {
1497 ArcIndexType degree(0);
1498 for (
auto arc ABSL_ATTRIBUTE_UNUSED : OppositeIncomingArcs(node)) ++degree;
1502template <
typename NodeIndexType,
typename ArcIndexType>
1504 ArcIndexType
arc)
const {
1509template <
typename NodeIndexType,
typename ArcIndexType>
1511 ArcIndexType
arc)
const {
1516template <
typename NodeIndexType,
typename ArcIndexType>
1518 ArcIndexType
arc)
const {
1519 return head_[OppositeArc(
arc)];
1522template <
typename NodeIndexType,
typename ArcIndexType>
1524 NodeIndexType
bound) {
1526 if (
bound <= num_nodes_)
return;
1527 start_.reserve(
bound);
1528 reverse_start_.reserve(
bound);
1531template <
typename NodeIndexType,
typename ArcIndexType>
1533 ArcIndexType
bound) {
1535 if (
bound <= num_arcs_)
return;
1536 head_.reserve(
bound);
1537 next_.reserve(
bound);
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);
1550template <
typename NodeIndexType,
typename ArcIndexType>
1552 NodeIndexType
tail, NodeIndexType
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_);
1564template <
typename NodeIndexType,
typename ArcIndexType>
1566 std::vector<ArcIndexType>* permutation) {
1567 if (permutation !=
nullptr) {
1568 permutation->clear();
1572template <
typename NodeIndexType,
typename ArcIndexType>
1573class ReverseArcListGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
1576 : graph_(
graph), index_(
graph.start_[node]) {
1582 DCHECK(
graph.IsNodeValid(node));
1587 ArcIndexType Index()
const {
return index_; }
1590 index_ = graph_.next_[index_];
1597 ArcIndexType index_;
1600template <
typename NodeIndexType,
typename ArcIndexType>
1607 DCHECK(
graph.IsNodeValid(node));
1610 NodeIndexType node, ArcIndexType
arc)
1612 DCHECK(
graph.IsNodeValid(node));
1618 ArcIndexType Index()
const {
return index_; }
1621 index_ = graph_.next_[index_];
1628 ArcIndexType index_;
1631template <
typename NodeIndexType,
typename ArcIndexType>
1644 ArcIndexType Index()
const {
1647 : this->graph_.OppositeArc(this->index_);
1653template <
typename NodeIndexType,
typename ArcIndexType>
1659 : graph_(
graph), index_(
graph.reverse_start_[node]), node_(node) {
1660 DCHECK(
graph.IsNodeValid(node));
1664 NodeIndexType node, ArcIndexType
arc)
1666 DCHECK(
graph.IsNodeValid(node));
1671 ArcIndexType Index()
const {
return index_; }
1675 index_ = graph_.next_[index_];
1677 index_ = graph_.start_[node_];
1680 index_ = graph_.next_[index_];
1688 ArcIndexType index_;
1689 const NodeIndexType node_;
1692template <
typename NodeIndexType,
typename ArcIndexType>
1696 : graph_(&
graph), index_(
graph.start_[node]) {
1702 DCHECK(
graph.IsNodeValid(node));
1707 ArcIndexType Index()
const {
return graph_->Head(index_); }
1710 index_ = graph_->next_[index_];
1717 ArcIndexType index_;
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];
1738template <
typename NodeIndexType,
typename ArcIndexType>
1740 NodeIndexType node)
const {
1741 return ReverseArcLimit(node) - reverse_start_[node];
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]);
1752template <
typename NodeIndexType,
typename ArcIndexType>
1754 ArcIndexType
arc)
const {
1756 DCHECK(IsArcValid(
arc));
1757 return opposite_[
arc];
1760template <
typename NodeIndexType,
typename ArcIndexType>
1762 ArcIndexType
arc)
const {
1764 DCHECK(IsArcValid(
arc));
1768template <
typename NodeIndexType,
typename ArcIndexType>
1770 ArcIndexType
arc)
const {
1772 return head_[OppositeArc(
arc)];
1775template <
typename NodeIndexType,
typename ArcIndexType>
1777 ArcIndexType
bound) {
1779 if (
bound <= num_arcs_)
return;
1780 head_.reserve(
bound);
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;
1791template <
typename NodeIndexType,
typename ArcIndexType>
1793 NodeIndexType
tail, NodeIndexType
head) {
1801 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
1805template <
typename NodeIndexType,
typename ArcIndexType>
1807 std::vector<ArcIndexType>* permutation) {
1809 if (is_built_)
return;
1811 node_capacity_ = num_nodes_;
1812 arc_capacity_ = num_arcs_;
1813 this->FreezeCapacities();
1814 this->BuildStartAndForwardHead(&head_, &start_, permutation);
1817 reverse_start_.assign(num_nodes_, 0);
1818 for (
int i = 0; i < num_arcs_; ++i) {
1819 reverse_start_[head_[i]]++;
1821 this->ComputeCumulativeSum(&reverse_start_);
1825 opposite_.reserve(num_arcs_);
1826 for (
int i = 0; i < num_arcs_; ++i) {
1828 opposite_.grow(0, reverse_start_[head_[i]]++ - num_arcs_);
1832 for (
int i = num_nodes_ - 1; i > 0; --i) {
1833 reverse_start_[i] = reverse_start_[i - 1] - num_arcs_;
1835 if (num_nodes_ != 0) {
1836 reverse_start_[0] = -num_arcs_;
1840 for (
int i = 0;
i < num_arcs_; ++
i) {
1841 opposite_[opposite_[
i]] =
i;
1843 for (
const NodeIndexType node : Base::AllNodes()) {
1844 for (
const ArcIndexType
arc : OutgoingArcs(node)) {
1845 head_[opposite_[
arc]] = node;
1850template <
typename NodeIndexType,
typename ArcIndexType>
1851class ReverseArcStaticGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
1858 DCHECK_GE(
arc,
graph.start_[node]);
1861 bool Ok()
const {
return index_ <
limit_; }
1862 ArcIndexType Index()
const {
return index_; }
1873 ArcIndexType index_;
1874 const ArcIndexType
limit_;
1877template <
typename NodeIndexType,
typename ArcIndexType>
1885 index_(
graph.reverse_start_[node]) {
1886 DCHECK(
graph.IsNodeValid(node));
1887 DCHECK_LE(index_,
limit_);
1890 NodeIndexType node, ArcIndexType
arc)
1892 DCHECK(
graph.IsNodeValid(node));
1893 DCHECK_GE(index_,
graph.reverse_start_[node]);
1894 DCHECK_LE(index_,
limit_);
1897 bool Ok()
const {
return index_ <
limit_; }
1898 ArcIndexType Index()
const {
return index_; }
1908 const ArcIndexType
limit_;
1909 ArcIndexType index_;
1912template <
typename NodeIndexType,
typename ArcIndexType>
1922 ?
graph.ReverseArcLimit(node)
1925 ArcIndexType Index()
const {
1926 return this->index_ == this->
limit_
1928 : this->graph_.OppositeArc(this->index_);
1934template <
typename NodeIndexType,
typename ArcIndexType>
1941 first_limit_(
graph.ReverseArcLimit(node)),
1942 next_start_(
graph.start_[node]),
1944 if (index_ == first_limit_) index_ = next_start_;
1945 DCHECK(
graph.IsNodeValid(node));
1946 DCHECK((index_ < first_limit_) || (index_ >= next_start_));
1949 NodeIndexType node, ArcIndexType
arc)
1951 first_limit_(
graph.ReverseArcLimit(node)),
1952 next_start_(
graph.start_[node]),
1954 DCHECK(
graph.IsNodeValid(node));
1955 DCHECK((index_ >=
graph.reverse_start_[node] && index_ < first_limit_) ||
1956 (index_ >= next_start_));
1959 ArcIndexType Index()
const {
return index_; }
1960 bool Ok()
const {
return index_ <
limit_; }
1964 if (index_ == first_limit_) {
1965 index_ = next_start_;
1972 ArcIndexType index_;
1973 const ArcIndexType first_limit_;
1974 const ArcIndexType next_start_;
1975 const ArcIndexType
limit_;
1981 DirectArcLimit(node));
1984 OutgoingOrOppositeIncoming,
1985 DirectArcLimit(node));
1989template <
typename NodeIndexType,
typename ArcIndexType>
1991 NodeIndexType node)
const {
1992 return DirectArcLimit(node) - start_[node];
1995template <
typename NodeIndexType,
typename ArcIndexType>
1997 NodeIndexType node)
const {
1998 ArcIndexType degree(0);
1999 for (
auto arc ABSL_ATTRIBUTE_UNUSED : OppositeIncomingArcs(node)) ++degree;
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]);
2011template <
typename NodeIndexType,
typename ArcIndexType>
2013 ArcIndexType
arc)
const {
2018template <
typename NodeIndexType,
typename ArcIndexType>
2020 ArcIndexType
arc)
const {
2022 DCHECK(IsArcValid(
arc));
2026template <
typename NodeIndexType,
typename ArcIndexType>
2028 ArcIndexType
arc)
const {
2030 return head_[OppositeArc(
arc)];
2033template <
typename NodeIndexType,
typename ArcIndexType>
2035 ArcIndexType
bound) {
2037 if (
bound <= num_arcs_)
return;
2038 head_.reserve(
bound);
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;
2049template <
typename NodeIndexType,
typename ArcIndexType>
2051 NodeIndexType
tail, NodeIndexType
head) {
2059 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
2063template <
typename NodeIndexType,
typename ArcIndexType>
2065 std::vector<ArcIndexType>* permutation) {
2067 if (is_built_)
return;
2069 node_capacity_ = num_nodes_;
2070 arc_capacity_ = num_arcs_;
2071 this->FreezeCapacities();
2072 this->BuildStartAndForwardHead(&head_, &start_, permutation);
2075 for (
const NodeIndexType node : Base::AllNodes()) {
2076 for (
const ArcIndexType
arc : OutgoingArcs(node)) {
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();
2090template <
typename NodeIndexType,
typename ArcIndexType>
2091class ReverseArcMixedGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
2098 DCHECK_GE(
arc,
graph.start_[node]);
2101 bool Ok()
const {
return index_ <
limit_; }
2102 ArcIndexType Index()
const {
return index_; }
2113 ArcIndexType index_;
2114 const ArcIndexType
limit_;
2117template <
typename NodeIndexType,
typename ArcIndexType>
2124 DCHECK(
graph.is_built_);
2125 DCHECK(
graph.IsNodeValid(node));
2126 index_ =
graph.reverse_start_[node];
2129 NodeIndexType node, ArcIndexType
arc)
2131 DCHECK(
graph.is_built_);
2132 DCHECK(
graph.IsNodeValid(node));
2137 ArcIndexType Index()
const {
return index_; }
2140 index_ = graph_->next_[~index_];
2147 ArcIndexType index_;
2150template <
typename NodeIndexType,
typename ArcIndexType>
2160 ArcIndexType Index()
const {
2163 : this->graph_->OppositeArc(this->index_);
2169template <
typename NodeIndexType,
typename ArcIndexType>
2177 index_ =
graph.reverse_start_[node];
2178 restart_ =
graph.start_[node];
2184 NodeIndexType node, ArcIndexType
arc)
2188 restart_ =
graph.start_[node];
2195 ArcIndexType Index()
const {
return index_; }
2199 index_ = graph_->next_[graph_->OppositeArc(index_)];
2212 ArcIndexType index_;
2213 ArcIndexType restart_;
2220template <
typename NodeIndexType =
int32_t,
typename ArcIndexType =
int32_t>
2238 NodeIndexType
Head(ArcIndexType
arc)
const;
2239 NodeIndexType
Tail(ArcIndexType
arc)
const;
2240 ArcIndexType
OutDegree(NodeIndexType node)
const;
2243 ArcIndexType from)
const;
2247template <
typename NodeIndexType,
typename ArcIndexType>
2249 ArcIndexType
arc)
const {
2250 DCHECK(this->IsArcValid(
arc));
2251 return arc % num_nodes_;
2254template <
typename NodeIndexType,
typename ArcIndexType>
2256 ArcIndexType
arc)
const {
2257 DCHECK(this->IsArcValid(
arc));
2258 return arc / num_nodes_;
2261template <
typename NodeIndexType,
typename ArcIndexType>
2263 NodeIndexType node)
const {
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));
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));
2286template <
typename NodeIndexType,
typename ArcIndexType>
2289 NodeIndexType node)
const {
2290 DCHECK_LT(node, num_nodes_);
2297template <
typename NodeIndexType =
int32_t,
typename ArcIndexType =
int32_t>
2299 :
public BaseGraph<NodeIndexType, ArcIndexType, false> {
2313 : left_nodes_(left_nodes), right_nodes_(right_nodes) {
2314 this->
Reserve(left_nodes + right_nodes, left_nodes * right_nodes);
2316 num_nodes_ = left_nodes + right_nodes;
2317 num_arcs_ = left_nodes * right_nodes;
2320 NodeIndexType
Head(ArcIndexType
arc)
const;
2321 NodeIndexType
Tail(ArcIndexType
arc)
const;
2322 ArcIndexType
OutDegree(NodeIndexType node)
const;
2325 ArcIndexType from)
const;
2329 class OutgoingArcIterator {
2332 : index_(
graph.right_nodes_ * node),
2333 limit_(node >=
graph.left_nodes_ ? index_
2334 :
graph.right_nodes_ * (node + 1)) {}
2336 bool Ok()
const {
return index_ < limit_; }
2337 ArcIndexType
Index()
const {
return index_; }
2341 ArcIndexType index_;
2342 const ArcIndexType limit_;
2346 const NodeIndexType left_nodes_;
2347 const NodeIndexType right_nodes_;
2350template <
typename NodeIndexType,
typename ArcIndexType>
2352 ArcIndexType
arc)
const {
2353 DCHECK(this->IsArcValid(
arc));
2354 return left_nodes_ +
arc % right_nodes_;
2357template <
typename NodeIndexType,
typename ArcIndexType>
2359 ArcIndexType
arc)
const {
2360 DCHECK(this->IsArcValid(
arc));
2361 return arc / right_nodes_;
2364template <
typename NodeIndexType,
typename ArcIndexType>
2366 NodeIndexType node)
const {
2367 return (node < left_nodes_) ? right_nodes_ : 0;
2370template <
typename NodeIndexType,
typename ArcIndexType>
2373 NodeIndexType node)
const {
2374 if (node < left_nodes_) {
2376 right_nodes_ * (node + 1));
2382template <
typename NodeIndexType,
typename ArcIndexType>
2383IntegerRange<ArcIndexType>
2385 NodeIndexType node, ArcIndexType from)
const {
2386 if (node < left_nodes_) {
2393template <
typename NodeIndexType,
typename ArcIndexType>
2394IntegerRange<NodeIndexType>
2396 NodeIndexType node)
const {
2397 if (node < left_nodes_) {
2405typedef ListGraph<>
Graph;
2409#undef DEFINE_RANGE_BASED_ARC_ITERATION
2410#undef DEFINE_STL_ITERATOR_FUNCTIONS
void GroupForwardArcsByFunctor(const A &a, B *b)
NodeIndexType num_nodes() const
bool IsArcValid(ArcIndexType arc) const
IntegerRange< NodeIndex > AllNodes() const
BaseGraph implementation -------------------------------------------------—.
ArcIndexType max_end_arc_index() const
NodeIndexType node_capacity_
NodeIndexType node_capacity() const
Capacity reserved for future nodes, always >= num_nodes_.
void BuildStartAndForwardHead(SVector< NodeIndexType > *head, std::vector< ArcIndexType > *start, std::vector< ArcIndexType > *permutation)
virtual void ReserveNodes(NodeIndexType bound)
BaseGraph & operator=(const BaseGraph &)=default
virtual ~BaseGraph()=default
ArcIndexType arc_capacity_
ArcIndexType arc_capacity() const
Capacity reserved for future arcs, always >= num_arcs_.
virtual void ReserveArcs(ArcIndexType bound)
static const NodeIndexType kNilNode
void Reserve(NodeIndexType node_capacity, ArcIndexType arc_capacity)
IntegerRange< ArcIndex > AllForwardArcs() const
bool IsNodeValid(NodeIndexType node) const
Returns true if the given node is a valid node of the graph.
void ComputeCumulativeSum(std::vector< ArcIndexType > *v)
Functions commented when defined because they are implementation details.
BaseGraph(const BaseGraph &)=default
static const ArcIndexType kNilArc
NodeIndexType size() const
ArcIndexType num_arcs() const
Returns the number of valid arcs in the graph.
OutgoingArcIterator(const CompleteBipartiteGraph &graph, NodeIndexType node)
ArcIndexType Index() const
NodeIndexType Tail(ArcIndexType arc) const
CompleteBipartiteGraph(NodeIndexType left_nodes, NodeIndexType right_nodes)
IntegerRange< ArcIndexType > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
IntegerRange< ArcIndexType > OutgoingArcs(NodeIndexType node) const
ArcIndexType OutDegree(NodeIndexType node) const
NodeIndexType Head(ArcIndexType arc) const
IntegerRange< NodeIndexType > operator[](NodeIndexType node) const
ArcIndexType OutDegree(NodeIndexType node) const
IntegerRange< ArcIndexType > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
IntegerRange< ArcIndexType > OutgoingArcs(NodeIndexType node) const
NodeIndexType Tail(ArcIndexType arc) const
IntegerRange< NodeIndexType > operator[](NodeIndexType node) const
CompleteGraph(NodeIndexType num_nodes)
Builds a complete graph with num_nodes nodes.
NodeIndexType Head(ArcIndexType arc) const
std::input_iterator_tag iterator_category
ptrdiff_t difference_type
const NodeIndexType * pointer
const NodeIndexType & reference
BeginEndWrapper< OutgoingHeadIterator > operator[](NodeIndexType node) const
ListGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
void AddNode(NodeIndexType node)
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
NodeIndexType Tail(ArcIndexType arc) const
Returns the tail/head of a valid arc.
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
ArcIndexType OutDegree(NodeIndexType node) const
NodeIndexType Head(ArcIndexType arc) const
void ReserveNodes(NodeIndexType bound) override
void ReserveArcs(ArcIndexType bound) override
IncomingArcIterator(const ReverseArcListGraph &graph, NodeIndexType node)
BeginEndWrapper< IncomingArcIterator > IncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
BeginEndWrapper< OutgoingHeadIterator > operator[](NodeIndexType node) const
NodeIndexType Head(ArcIndexType arc) const
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcs(NodeIndexType node) const
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcs(NodeIndexType node) const
void ReserveArcs(ArcIndexType bound) override
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
ReverseArcListGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
ArcIndexType OppositeArc(ArcIndexType arc) const
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
void AddNode(NodeIndexType node)
BeginEndWrapper< IncomingArcIterator > IncomingArcs(NodeIndexType node) const
NodeIndexType Tail(ArcIndexType arc) const
ArcIndexType OutDegree(NodeIndexType node) const
ReverseArcListGraph<>::OutDegree() and InDegree() work in O(degree).
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
void ReserveNodes(NodeIndexType bound) override
ArcIndexType InDegree(NodeIndexType node) const
IncomingArcIterator(const ReverseArcMixedGraph &graph, NodeIndexType node)
OutgoingArcIterator(const ReverseArcMixedGraph &graph, NodeIndexType node)
NodeIndexType Tail(ArcIndexType arc) const
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
NodeIndexType Head(ArcIndexType arc) const
ReverseArcMixedGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
ArcIndexType OppositeArc(ArcIndexType arc) const
BeginEndWrapper< IncomingArcIterator > IncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
void AddNode(NodeIndexType node)
BeginEndWrapper< IncomingArcIterator > IncomingArcs(NodeIndexType node) const
absl::Span< const NodeIndexType > operator[](NodeIndexType node) const
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
void ReserveArcs(ArcIndexType bound) override
ArcIndexType OutDegree(NodeIndexType node) const
ArcIndexType InDegree(NodeIndexType node) const
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)
OutgoingArcIterator(const ReverseArcStaticGraph &graph, NodeIndexType node)
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
NodeIndexType Tail(ArcIndexType arc) const
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
BeginEndWrapper< IncomingArcIterator > IncomingArcs(NodeIndexType node) const
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcs(NodeIndexType node) const
absl::Span< const NodeIndexType > operator[](NodeIndexType node) const
NodeIndexType Head(ArcIndexType arc) const
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
void ReserveArcs(ArcIndexType bound) override
ArcIndexType OutDegree(NodeIndexType node) const
ReverseArcStaticGraph<>::OutDegree() and InDegree() work in O(1).
ArcIndexType InDegree(NodeIndexType node) const
ReverseArcStaticGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
void AddNode(NodeIndexType node)
const T & operator[](int n) const
SVector & operator=(SVector &&other) noexcept
SVector(const SVector &other)
Copy constructor and assignment operator.
SVector(SVector &&other) noexcept
Move constructor and move assignment operator.
void swap(SVector< T > &x) noexcept
void grow(const T &left=T(), const T &right=T())
SVector & operator=(const SVector &other)
OutgoingArcIterator(const StaticGraph &graph, NodeIndexType node)
absl::Span< const NodeIndexType > operator[](NodeIndexType node) const
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
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
NodeIndexType Tail(ArcIndexType arc) const
void ReserveArcs(ArcIndexType bound) override
void ReserveNodes(NodeIndexType bound) override
void AddNode(NodeIndexType node)
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
StaticGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
NodeIndexType Head(ArcIndexType arc) const
#define DEFINE_RANGE_BASED_ARC_ITERATION(c, t, e)
#define DEFINE_STL_ITERATOR_FUNCTIONS(iterator_class_name)
A collections of i/o utilities for the Graph classes in ./graph.h.
void Permute(const IntVector &permutation, Array *array_to_permute)
void PermuteWithExplicitElementType(const IntVector &permutation, Array *array_to_permute, ElementType unused)
ListGraph Graph
Defining the simplest Graph interface as Graph for convenience.
trees with all degrees equal to