113 ArcLengthFunctor arc_length_functor);
120 DistanceType distance_limit) {
140 const std::vector<std::pair<int, DistanceType>>&
141 sources_with_distance_offsets,
142 DistanceType distance_limit);
166 const std::vector<std::pair<int, DistanceType>>&
167 sources_with_distance_offsets,
168 const std::vector<std::pair<int, DistanceType>>&
169 destinations_with_distance_offsets,
170 int num_destinations_to_reach, DistanceType distance_limit);
178 const std::vector<std::pair<int, DistanceType>>&
179 sources_with_distance_offsets,
180 std::function<
void(
node_type settled_node, DistanceType settled_distance,
181 DistanceType* distance_limit)>
182 settled_node_callback,
183 DistanceType distance_limit);
197 const std::vector<DistanceType>&
distances()
const {
return distances_; }
206 const std::vector<int>&
parents()
const {
return parents_; }
214 std::vector<int>
ArcPathTo(
int node)
const;
216 ABSL_DEPRECATED(
"Use ArcPathTo() instead.")
246 const GraphType&
graph()
const {
return *graph_; }
249 return *arc_lengths_;
252 const DistanceType length = arc_length_functor_(
arc);
253 DCHECK_GE(length, 0);
263 const GraphType*
const graph_;
264 ArcLengthFunctor arc_length_functor_;
265 const std::vector<DistanceType>*
const arc_lengths_;
268 std::vector<DistanceType> distances_;
269 std::vector<int> parents_;
270 std::vector<int> arc_from_source_;
271 std::vector<bool> is_reached_;
272 std::vector<int> reached_nodes_;
275 struct NodeDistance {
277 DistanceType distance;
279 bool operator<(
const NodeDistance& other)
const {
295 return std::tie(distance, node) < std::tie(other.distance, other.node);
297 bool operator>(
const NodeDistance& other)
const {
return other < *
this; }
299 std::vector<NodeDistance> queue_;
305 std::vector<bool> is_destination_;
306 std::vector<int> node_to_source_index_;
307 std::vector<int> node_to_destination_index_;
358 const std::vector<std::pair<int, DistanceType>>&
359 sources_with_distance_offsets,
360 const std::vector<std::pair<int, DistanceType>>&
361 destinations_with_distance_offsets,
362 int num_destinations_to_reach, DistanceType distance_limit) {
363 if (destinations_with_distance_offsets.empty())
return {};
364 if (num_destinations_to_reach <= 0)
return {};
369 DCHECK_GE(num_destinations_to_reach, 0);
370 int num_destinations = 0;
371 is_destination_.resize(graph_->num_nodes(),
false);
372 node_to_destination_index_.resize(graph_->num_nodes(), -1);
373 DistanceType min_destination_distance_offset =
374 destinations_with_distance_offsets[0].second;
375 for (
int i = 0; i < destinations_with_distance_offsets.size(); ++i) {
376 const int node = destinations_with_distance_offsets[i].first;
377 const DistanceType
distance = destinations_with_distance_offsets[i].second;
378 if (!is_destination_[node]) ++num_destinations;
380 if (is_destination_[node] &&
382 destinations_with_distance_offsets[node_to_destination_index_[node]]
386 is_destination_[node] =
true;
387 node_to_destination_index_[node] = i;
388 min_destination_distance_offset =
389 std::min(min_destination_distance_offset,
distance);
391 distance_limit -= min_destination_distance_offset;
392 if (num_destinations_to_reach > num_destinations) {
393 num_destinations_to_reach = num_destinations;
396 num_destinations_to_reach);
398 std::function<void(
node_type, DistanceType, DistanceType*)>
399 settled_node_callback =
400 [
this, num_destinations_to_reach, min_destination_distance_offset,
401 &destinations_with_distance_offsets, &closest_destinations](
402 node_type settled_node, DistanceType settled_distance,
403 DistanceType* distance_limit) {
404 if (!is_destination_[settled_node])
return;
407 destinations_with_distance_offsets
408 [node_to_destination_index_[settled_node]]
410 min_destination_distance_offset;
411 if (
distance >= *distance_limit)
return;
412 closest_destinations.push(NodeDistance{settled_node,
distance});
413 if (closest_destinations.size() == num_destinations_to_reach) {
414 const DistanceType new_distance_limit =
415 closest_destinations.peek_bottom().distance;
416 DCHECK_LE(new_distance_limit, *distance_limit);
417 *distance_limit = new_distance_limit;
421 RunBoundedDijkstraWithSettledNodeCallback(
422 sources_with_distance_offsets, settled_node_callback, distance_limit);
425 for (
const auto& [node, _] : destinations_with_distance_offsets) {
426 is_destination_[node] =
false;
431 std::vector<int> sorted_destinations;
432 sorted_destinations.reserve(closest_destinations.size());
433 for (
const NodeDistance& d : closest_destinations.Take()) {
434 sorted_destinations.push_back(d.node);
436 return sorted_destinations;
439template <
class GraphType,
class DistanceType,
class ArcLengthFunctor>
462 const std::vector<std::pair<int, DistanceType>>&
463 sources_with_distance_offsets,
464 std::function<
void(
node_type settled_node,
465 DistanceType settled_distance,
466 DistanceType* distance_limit)>
467 settled_node_callback,
468 DistanceType distance_limit) {
470 for (
const int node : reached_nodes_) {
471 is_reached_[node] =
false;
473 reached_nodes_.clear();
474 DCHECK(!absl::c_linear_search(is_reached_,
true));
476 is_reached_.resize(graph_->num_nodes(),
false);
477 distances_.resize(graph_->num_nodes(), distance_limit);
478 parents_.resize(graph_->num_nodes(), std::numeric_limits<int>::min());
479 arc_from_source_.resize(graph_->num_nodes(), -1);
482 CHECK(queue_.empty());
483 node_to_source_index_.resize(graph_->num_nodes(), -1);
484 for (
int i = 0; i < sources_with_distance_offsets.size(); ++i) {
485 const int node = sources_with_distance_offsets[i].first;
487 DCHECK_LT(node, graph_->num_nodes());
488 const DistanceType
distance = sources_with_distance_offsets[i].second;
490 if (
distance >= distance_limit)
continue;
492 if (is_reached_[node] &&
distance >= distances_[node])
continue;
493 if (!is_reached_[node]) {
494 is_reached_[node] =
true;
495 reached_nodes_.push_back(node);
496 parents_[node] = node;
498 node_to_source_index_[node] = i;
501 for (
const int source : reached_nodes_) {
502 queue_.push_back({source, distances_[source]});
504 std::make_heap(queue_.begin(), queue_.end(), std::greater<NodeDistance>());
507 while (!queue_.empty()) {
508 const NodeDistance top = queue_.front();
509 std::pop_heap(queue_.begin(), queue_.end(), std::greater<NodeDistance>());
514 if (distances_[top.node] < top.distance)
continue;
516 if (settled_node_callback) {
521 if (top.distance < distance_limit) {
522 settled_node_callback(top.node, top.distance, &distance_limit);
526 if (top.distance >= distance_limit) {
531 DCHECK_LT(top.distance, distance_limit);
535 const DistanceType limit = distance_limit - top.distance;
536 for (
const int arc : graph_->OutgoingArcs(top.node)) {
542 const DistanceType arc_length = GetArcLength(
arc);
543 if (arc_length >= limit)
continue;
544 const DistanceType candidate_distance = top.distance + arc_length;
546 const int head = graph_->Head(
arc);
547 if (is_reached_[
head]) {
548 if (candidate_distance >= distances_[
head])
continue;
550 is_reached_[
head] =
true;
551 reached_nodes_.push_back(
head);
553 distances_[
head] = candidate_distance;
554 parents_[
head] = top.node;
556 queue_.push_back({
head, candidate_distance});
557 std::push_heap(queue_.begin(), queue_.end(),
558 std::greater<NodeDistance>());
562 return reached_nodes_;
565template <
class GraphType,
class DistanceType,
class ArcLengthFunctor>
640 CHECK_GE(destination, 0);
641 int num_nodes = std::max(source + 1, destination + 1);
642 for (
const int tail : tails) {
644 num_nodes = std::max(
tail + 1, num_nodes);
646 for (
const int head : heads) {
648 num_nodes = std::max(
head + 1, num_nodes);
652 const int num_arcs = tails.size();
653 CHECK_EQ(num_arcs, heads.size());
654 CHECK_EQ(num_arcs, lengths.size());
659 std::vector<DistanceType>
arc_lengths(lengths.begin(), lengths.end());
660 for (
int a = 0;
a < num_arcs; ++
a) {
663 CHECK_GE(lengths[
a], 0);
664 graph.AddArc(tails[
a], heads[
a]);
666 std::vector<int> permutation;
667 graph.Build(&permutation);
672 BoundedDijkstraWrapper<util::StaticGraph<>, DistanceType> wrapper(
674 if (!wrapper.OneToOneShortestPath(source, destination, limit)) {
680 return {wrapper.distances()[destination], wrapper.NodePathTo(destination)};