#include <compare> #include <iostream> #include <optional> #include <print> #include <ranges> #include <set> #include <vector> class Edge { public: int toIdx; int weight; }; std::vector<std::optional<int>> shortestPaths(std::vector<std::vector<Edge>> const& graph, int startIdx) { class DijkstraState { public: int idx; int distance; }; auto compareState = [](auto const& state1, auto const& state2) -> bool { if (auto cmp = state1.distance <=> state2.distance; std::is_neq(cmp)) { return std::is_lt(cmp); } if (auto cmp = state1.idx <=> state2.idx; std::is_neq(cmp)) { return std::is_lt(cmp); } return 0; }; std::vector<std::optional<int>> distances(graph.size(), std::nullopt); distances[startIdx] = 0; std::set<DijkstraState, decltype(compareState)> states {{startIdx, 0}}; while (!states.empty()) { auto curState = *states.begin(); states.erase(states.begin()); for (auto const& outEdge: graph[curState.idx]) { auto& currentBestDistance = distances[outEdge.toIdx]; int potentialDistance = curState.distance + outEdge.weight; if (!currentBestDistance) { states.emplace(outEdge.toIdx, potentialDistance); currentBestDistance = potentialDistance; } else if (*currentBestDistance > potentialDistance) { auto nodeHandle = states.extract({outEdge.toIdx, *currentBestDistance}); currentBestDistance = potentialDistance; nodeHandle.value().distance = potentialDistance; states.insert(std::move(nodeHandle)).position; } } } return distances; } int main() { auto graph = std::vector<std::vector<Edge>> { {{3, 3}}, {{0, 5}, {2, 1}}, {{0, 2}, {3, 10}}, {}, {} }; auto distances = shortestPaths(graph, 1); for (auto const& [idx, distance]: distances | std::views::enumerate) { std::println("{}'s distance is {}", idx, distance ? *distance : -1); } }