diff --git a/lib/Graph/dijkstra.h b/lib/Graph/dijkstra.h new file mode 100644 index 0000000..8da9536 --- /dev/null +++ b/lib/Graph/dijkstra.h @@ -0,0 +1,69 @@ +#pragma once +#include "graph.h" +#include "template.h" + +template +class Dijkstra { + private: + T INF = numeric_limits::max() / 10; + int V; // 頂点数 + AdjList adj; // adj[始点][動的配列で始点から伸びる枝] + vector prever; + + public: + explicit Dijkstra(int n); + vector cost; + void AddEdge(int f, int t, int c); + bool HasPath(int t); // tに至るパスはあるか + vector GetShortestPath(int t); // tへの最短路 + void Run(int f); +}; + +template +Dijkstra::Dijkstra(int n) + : V(n + 1), adj(V), prever(vector(V, -1)), cost(V) { + fill(cost.begin(), cost.end(), INF); +} + +template +void Dijkstra::AddEdge(int f, int t, int c) { + adj[f].push_back(Edge(t, c)); +} + +template +bool Dijkstra::HasPath(int t) { + return cost[t] != INF; +} + +template +vector Dijkstra::GetShortestPath(int t) { + vector path; + for (; t != -1; t = prever[t]) path.push_back(t); + + reverse(path.begin(), path.end()); + return path; +} + +template +void Dijkstra::Run(int firstNode) { + using Pi = pair; + priority_queue, greater> pq; + + cost[firstNode] = 0; + pq.push(Pi(cost[firstNode], firstNode)); + + while (!pq.empty()) { + Pi currentEdge = pq.top(); + pq.pop(); + if (cost[currentEdge.second] < currentEdge.first) continue; + + for (Edge tmp : adj[currentEdge.second]) { + T sumCost = currentEdge.first + tmp.cost; + if (cost[tmp.to] > sumCost) { + cost[tmp.to] = sumCost; + prever[tmp.to] = currentEdge.second; + pq.push(Pi(cost[tmp.to], tmp.to)); + } + } + } +}