71 NodeIndexType
Head(ArcIndexType arc)
const {
74 DCHECK_LT(arc, num_arcs_);
78 NodeIndexType
Tail(ArcIndexType arc)
const {
81 DCHECK_LT(arc, num_arcs_);
87 return heads_[reverse_[arc]];
95 DCHECK_LT(arc, num_arcs_);
104 NodeIndexType node, ArcIndexType from)
const {
107 DCHECK_LT(node, num_nodes_);
108 DCHECK_GE(from, start_[node]);
116 NodeIndexType node)
const {
120 NodeIndexType node, ArcIndexType from)
const {
124 absl::Span<const NodeIndexType>
operator[](NodeIndexType node)
const {
125 const int b = start_[node];
126 const size_t size = start_[node + 1] - b;
127 if (
size == 0)
return {};
128 return {&heads_[b],
size};
133 tmp_tails_.reserve(bound);
134 tmp_heads_.reserve(bound);
138 num_nodes_ = std::max(num_nodes_, node + 1);
141 ArcIndexType
AddArc(NodeIndexType tail, NodeIndexType head) {
142 AddNode(tail > head ? tail : head);
143 tmp_tails_.push_back(tail);
144 tmp_heads_.push_back(head);
149 void Build(std::vector<ArcIndexType>* permutation);
166 void FillPermutationAndStart(absl::Span<const NodeIndexType>
input,
167 absl::Span<ArcIndexType> perm);
172 void FillPermutationAndStart(absl::Span<const NodeIndexType> first_criteria,
173 absl::Span<const NodeIndexType> second_criteria,
174 absl::Span<ArcIndexType> perm);
175 void FillReversePermutationAndStart(
176 absl::Span<const NodeIndexType> first_criteria,
177 absl::Span<const NodeIndexType> second_criteria,
178 absl::Span<ArcIndexType> reverse_perm);
181 void InitializeStart(absl::Span<const NodeIndexType>
input);
185 bool option_detect_reverse_ =
true;
186 bool option_sort_by_head_ =
false;
191 bool is_built_ =
false;
194 std::vector<NodeIndexType> tmp_tails_;
195 std::vector<NodeIndexType> tmp_heads_;
199 std::unique_ptr<ArcIndexType[]> start_;
203 std::unique_ptr<NodeIndexType[]> heads_;
205 std::unique_ptr<ArcIndexType[]> reverse_;
315 std::vector<ArcIndexType>* permutation) {
317 if (is_built_)
return;
320 start_ = std::make_unique<ArcIndexType[]>(num_nodes_ + 1);
321 std::vector<ArcIndexType> perm(num_arcs_);
323 const int kNoExplicitReverseArc = -1;
324 std::vector<ArcIndexType> reverse(num_arcs_, kNoExplicitReverseArc);
326 bool fix_final_permutation =
false;
327 if (option_detect_reverse_) {
330 std::vector<bool> was_reversed_(num_arcs_,
false);
331 for (
int arc = 0; arc < num_arcs_; ++arc) {
332 if (tmp_heads_[arc] < tmp_tails_[arc]) {
333 std::swap(tmp_heads_[arc], tmp_tails_[arc]);
334 was_reversed_[arc] =
true;
341 auto reverse_perm = absl::MakeSpan(perm);
342 FillReversePermutationAndStart(tmp_tails_, tmp_heads_,
343 absl::MakeSpan(reverse_perm));
349 for (
int i = 0; i < num_arcs_; ++i) {
350 const int arc = reverse_perm[i];
351 const int candidate_arc = reverse_perm[candidate_i];
352 if (tmp_heads_[arc] != tmp_heads_[candidate_arc] ||
353 tmp_tails_[arc] != tmp_tails_[candidate_arc]) {
358 if (was_reversed_[arc] != was_reversed_[candidate_arc]) {
359 DCHECK_EQ(reverse[arc], -1);
360 DCHECK_EQ(reverse[candidate_arc], -1);
361 reverse[arc] = candidate_arc;
362 reverse[candidate_arc] = arc;
366 for (; ++candidate_i < i;) {
367 if (reverse[reverse_perm[candidate_i]] == -1)
break;
369 if (candidate_i == i) {
377 const int extra_size = num_arcs_ - num_filled;
378 tmp_tails_.resize(num_arcs_ + extra_size);
379 tmp_heads_.resize(num_arcs_ + extra_size);
380 reverse.resize(num_arcs_ + extra_size);
381 int new_index = num_arcs_;
382 for (
int i = 0; i < num_arcs_; ++i) {
384 if (was_reversed_[i]) {
385 std::swap(tmp_tails_[i], tmp_heads_[i]);
388 if (reverse[i] != kNoExplicitReverseArc)
continue;
389 reverse[i] = new_index;
390 reverse[new_index] = i;
391 tmp_tails_[new_index] = tmp_heads_[i];
392 tmp_heads_[new_index] = tmp_tails_[i];
395 CHECK_EQ(new_index, num_arcs_ + extra_size);
399 tmp_tails_.resize(2 * num_arcs_);
400 tmp_heads_.resize(2 * num_arcs_);
401 reverse.resize(2 * num_arcs_);
402 for (
int arc = 0; arc < num_arcs_; ++arc) {
403 const int image = num_arcs_ + arc;
404 tmp_heads_[image] = tmp_tails_[arc];
405 tmp_tails_[image] = tmp_heads_[arc];
406 reverse[image] = arc;
407 reverse[arc] = image;
416 fix_final_permutation =
true;
417 for (
int arc = 0; arc < num_arcs_; ++arc) {
418 const int image = num_arcs_ + arc;
419 std::swap(tmp_heads_[image], tmp_heads_[arc]);
420 std::swap(tmp_tails_[image], tmp_tails_[arc]);
424 num_arcs_ = tmp_heads_.size();
425 perm.resize(num_arcs_);
432 if (option_sort_by_head_) {
433 FillPermutationAndStart(tmp_tails_, tmp_heads_, absl::MakeSpan(perm));
435 FillPermutationAndStart(tmp_tails_, absl::MakeSpan(perm));
439 heads_ = std::make_unique<NodeIndexType[]>(num_arcs_);
441 perm, tmp_heads_, absl::MakeSpan(heads_.get(), num_arcs_));
448 reverse_ = std::make_unique<ArcIndexType[]>(num_arcs_);
449 for (
int i = 0; i < num_arcs_; ++i) {
450 reverse_[perm[i]] = perm[reverse[i]];
453 if (permutation !=
nullptr) {
454 if (fix_final_permutation) {
455 for (
int i = 0; i < num_arcs_ / 2; ++i) {
456 std::swap(perm[i], perm[num_arcs_ / 2 + i]);
459 permutation->swap(perm);
462 node_capacity_ = num_nodes_;
463 arc_capacity_ = num_arcs_;