53 NodeIndexType, ArcIndexType, false> {
74 NodeIndexType
Head(ArcIndexType arc)
const {
77 DCHECK_LT(arc, num_arcs_);
81 NodeIndexType
Tail(ArcIndexType arc)
const {
84 DCHECK_LT(arc, num_arcs_);
90 return heads_[reverse_[arc]];
98 DCHECK_LT(arc, num_arcs_);
107 NodeIndexType node, ArcIndexType from)
const {
110 DCHECK_LT(node, num_nodes_);
111 DCHECK_GE(from, start_[node]);
119 NodeIndexType node)
const {
123 NodeIndexType node, ArcIndexType from)
const {
127 absl::Span<const NodeIndexType>
operator[](NodeIndexType node)
const {
128 const int b = start_[node];
129 const size_t size = start_[node + 1] - b;
130 if (
size == 0)
return {};
131 return {&heads_[b],
size};
136 tmp_tails_.reserve(bound);
137 tmp_heads_.reserve(bound);
141 num_nodes_ = std::max(num_nodes_, node + 1);
144 ArcIndexType
AddArc(NodeIndexType tail, NodeIndexType head) {
145 AddNode(tail > head ? tail : head);
146 tmp_tails_.push_back(tail);
147 tmp_heads_.push_back(head);
152 void Build(std::vector<ArcIndexType>* permutation)
final;
169 void FillPermutationAndStart(absl::Span<const NodeIndexType>
input,
170 absl::Span<ArcIndexType> perm);
175 void FillPermutationAndStart(absl::Span<const NodeIndexType> first_criteria,
176 absl::Span<const NodeIndexType> second_criteria,
177 absl::Span<ArcIndexType> perm);
178 void FillReversePermutationAndStart(
179 absl::Span<const NodeIndexType> first_criteria,
180 absl::Span<const NodeIndexType> second_criteria,
181 absl::Span<ArcIndexType> reverse_perm);
184 void InitializeStart(absl::Span<const NodeIndexType>
input);
188 bool option_detect_reverse_ =
true;
189 bool option_sort_by_head_ =
false;
194 bool is_built_ =
false;
197 std::vector<NodeIndexType> tmp_tails_;
198 std::vector<NodeIndexType> tmp_heads_;
202 std::unique_ptr<ArcIndexType[]> start_;
206 std::unique_ptr<NodeIndexType[]> heads_;
208 std::unique_ptr<ArcIndexType[]> reverse_;
318 std::vector<ArcIndexType>* permutation) {
320 if (is_built_)
return;
323 start_ = std::make_unique<ArcIndexType[]>(num_nodes_ + 1);
324 std::vector<ArcIndexType> perm(num_arcs_);
326 const int kNoExplicitReverseArc = -1;
327 std::vector<ArcIndexType> reverse(num_arcs_, kNoExplicitReverseArc);
329 bool fix_final_permutation =
false;
330 if (option_detect_reverse_) {
333 std::vector<bool> was_reversed_(num_arcs_,
false);
334 for (
int arc = 0; arc < num_arcs_; ++arc) {
335 if (tmp_heads_[arc] < tmp_tails_[arc]) {
336 std::swap(tmp_heads_[arc], tmp_tails_[arc]);
337 was_reversed_[arc] =
true;
344 auto reverse_perm = absl::MakeSpan(perm);
345 FillReversePermutationAndStart(tmp_tails_, tmp_heads_,
346 absl::MakeSpan(reverse_perm));
352 for (
int i = 0; i < num_arcs_; ++i) {
353 const int arc = reverse_perm[i];
354 const int candidate_arc = reverse_perm[candidate_i];
355 if (tmp_heads_[arc] != tmp_heads_[candidate_arc] ||
356 tmp_tails_[arc] != tmp_tails_[candidate_arc]) {
361 if (was_reversed_[arc] != was_reversed_[candidate_arc]) {
362 DCHECK_EQ(reverse[arc], -1);
363 DCHECK_EQ(reverse[candidate_arc], -1);
364 reverse[arc] = candidate_arc;
365 reverse[candidate_arc] = arc;
369 for (; ++candidate_i < i;) {
370 if (reverse[reverse_perm[candidate_i]] == -1)
break;
372 if (candidate_i == i) {
380 const int extra_size = num_arcs_ - num_filled;
381 tmp_tails_.resize(num_arcs_ + extra_size);
382 tmp_heads_.resize(num_arcs_ + extra_size);
383 reverse.resize(num_arcs_ + extra_size);
384 int new_index = num_arcs_;
385 for (
int i = 0; i < num_arcs_; ++i) {
387 if (was_reversed_[i]) {
388 std::swap(tmp_tails_[i], tmp_heads_[i]);
391 if (reverse[i] != kNoExplicitReverseArc)
continue;
392 reverse[i] = new_index;
393 reverse[new_index] = i;
394 tmp_tails_[new_index] = tmp_heads_[i];
395 tmp_heads_[new_index] = tmp_tails_[i];
398 CHECK_EQ(new_index, num_arcs_ + extra_size);
402 tmp_tails_.resize(2 * num_arcs_);
403 tmp_heads_.resize(2 * num_arcs_);
404 reverse.resize(2 * num_arcs_);
405 for (
int arc = 0; arc < num_arcs_; ++arc) {
406 const int image = num_arcs_ + arc;
407 tmp_heads_[image] = tmp_tails_[arc];
408 tmp_tails_[image] = tmp_heads_[arc];
409 reverse[image] = arc;
410 reverse[arc] = image;
419 fix_final_permutation =
true;
420 for (
int arc = 0; arc < num_arcs_; ++arc) {
421 const int image = num_arcs_ + arc;
422 std::swap(tmp_heads_[image], tmp_heads_[arc]);
423 std::swap(tmp_tails_[image], tmp_tails_[arc]);
427 num_arcs_ = tmp_heads_.size();
428 perm.resize(num_arcs_);
435 if (option_sort_by_head_) {
436 FillPermutationAndStart(tmp_tails_, tmp_heads_, absl::MakeSpan(perm));
438 FillPermutationAndStart(tmp_tails_, absl::MakeSpan(perm));
442 heads_ = std::make_unique<NodeIndexType[]>(num_arcs_);
444 perm, tmp_heads_, absl::MakeSpan(heads_.get(), num_arcs_));
451 reverse_ = std::make_unique<ArcIndexType[]>(num_arcs_);
452 for (
int i = 0; i < num_arcs_; ++i) {
453 reverse_[perm[i]] = perm[reverse[i]];
456 if (permutation !=
nullptr) {
457 if (fix_final_permutation) {
458 for (
int i = 0; i < num_arcs_ / 2; ++i) {
459 std::swap(perm[i], perm[num_arcs_ / 2 + i]);
462 permutation->swap(perm);
465 node_capacity_ = num_nodes_;
466 arc_capacity_ = num_arcs_;