ダイクストラ法
(shortest-path/dijkstra.hpp)
- View this file on GitHub
- Last update: 2024-05-03 23:21:26+09:00
- Include:
#include "shortest-path/dijkstra.hpp"
ダイクストラ法
ダイクストラ法を$\mathrm{O}(E \log V)$で行うライブラリ。
概要
ダイクストラ法とは負辺の無い有向グラフでの単一始点最短経路を$\mathrm{O}(E \log V)$で計算するアルゴリズムである。基数ヒープやフィボナッチヒープを用いた高速化も知られている。
使い方
-
dijkstra(g, start = 0)
: sを始点としたダイクストラ法を行い、sからの距離(到達できない場合-1
)が格納された配列を返す。
Depends on
Verified with
verify/verify-aoj-grl/aoj-grl-1-a.test.cpp
verify/verify-aoj-other/aoj-2171-bigrational.test.cpp
verify/verify-aoj-other/aoj-2171.test.cpp
verify/verify-unit-test/dijkstra.test.cpp
verify/verify-unit-test/dynamic-diameter.test.cpp
verify/verify-yosupo-graph/yosupo-shortest-path.test.cpp
Code
#pragma once
#include "../graph/graph-template.hpp"
// unreachable -> -1
template <typename T>
vector<T> dijkstra(WeightedGraph<T> &g, int start = 0) {
using P = pair<T, int>;
int N = (int)g.size();
vector<T> d(N, T(-1));
priority_queue<P, vector<P>, greater<P> > Q;
d[start] = 0;
Q.emplace(0, start);
while (!Q.empty()) {
P p = Q.top();
Q.pop();
int cur = p.second;
if (d[cur] < p.first) continue;
for (auto dst : g[cur]) {
if (d[dst] == T(-1) || d[cur] + dst.cost < d[dst]) {
d[dst] = d[cur] + dst.cost;
Q.emplace(d[dst], dst);
}
}
}
return d;
}
/**
* @brief ダイクストラ法
* @docs docs/shortest-path/dijkstra.md
*/
#line 2 "shortest-path/dijkstra.hpp"
#line 2 "graph/graph-template.hpp"
template <typename T>
struct edge {
int src, to;
T cost;
edge(int _to, T _cost) : src(-1), to(_to), cost(_cost) {}
edge(int _src, int _to, T _cost) : src(_src), to(_to), cost(_cost) {}
edge &operator=(const int &x) {
to = x;
return *this;
}
operator int() const { return to; }
};
template <typename T>
using Edges = vector<edge<T>>;
template <typename T>
using WeightedGraph = vector<Edges<T>>;
using UnweightedGraph = vector<vector<int>>;
// Input of (Unweighted) Graph
UnweightedGraph graph(int N, int M = -1, bool is_directed = false,
bool is_1origin = true) {
UnweightedGraph g(N);
if (M == -1) M = N - 1;
for (int _ = 0; _ < M; _++) {
int x, y;
cin >> x >> y;
if (is_1origin) x--, y--;
g[x].push_back(y);
if (!is_directed) g[y].push_back(x);
}
return g;
}
// Input of Weighted Graph
template <typename T>
WeightedGraph<T> wgraph(int N, int M = -1, bool is_directed = false,
bool is_1origin = true) {
WeightedGraph<T> g(N);
if (M == -1) M = N - 1;
for (int _ = 0; _ < M; _++) {
int x, y;
cin >> x >> y;
T c;
cin >> c;
if (is_1origin) x--, y--;
g[x].emplace_back(x, y, c);
if (!is_directed) g[y].emplace_back(y, x, c);
}
return g;
}
// Input of Edges
template <typename T>
Edges<T> esgraph([[maybe_unused]] int N, int M, int is_weighted = true,
bool is_1origin = true) {
Edges<T> es;
for (int _ = 0; _ < M; _++) {
int x, y;
cin >> x >> y;
T c;
if (is_weighted)
cin >> c;
else
c = 1;
if (is_1origin) x--, y--;
es.emplace_back(x, y, c);
}
return es;
}
// Input of Adjacency Matrix
template <typename T>
vector<vector<T>> adjgraph(int N, int M, T INF, int is_weighted = true,
bool is_directed = false, bool is_1origin = true) {
vector<vector<T>> d(N, vector<T>(N, INF));
for (int _ = 0; _ < M; _++) {
int x, y;
cin >> x >> y;
T c;
if (is_weighted)
cin >> c;
else
c = 1;
if (is_1origin) x--, y--;
d[x][y] = c;
if (!is_directed) d[y][x] = c;
}
return d;
}
/**
* @brief グラフテンプレート
* @docs docs/graph/graph-template.md
*/
#line 4 "shortest-path/dijkstra.hpp"
// unreachable -> -1
template <typename T>
vector<T> dijkstra(WeightedGraph<T> &g, int start = 0) {
using P = pair<T, int>;
int N = (int)g.size();
vector<T> d(N, T(-1));
priority_queue<P, vector<P>, greater<P> > Q;
d[start] = 0;
Q.emplace(0, start);
while (!Q.empty()) {
P p = Q.top();
Q.pop();
int cur = p.second;
if (d[cur] < p.first) continue;
for (auto dst : g[cur]) {
if (d[dst] == T(-1) || d[cur] + dst.cost < d[dst]) {
d[dst] = d[cur] + dst.cost;
Q.emplace(d[dst], dst);
}
}
}
return d;
}
/**
* @brief ダイクストラ法
* @docs docs/shortest-path/dijkstra.md
*/