--- tags: APCS --- # Dijkstra 演算法 ``` graphviz graph G { splines="line" rankdir=LR node[shape=circle] {rank=same;1,2} {rank=same;3,4} 0 -- 1 [label=4] 0 -- 2 [label=2] 1 -- 2 [label=1] 1 -- 3 [label=5] 2 -- 3 [label=8] 2 -- 4 [label=10] 3 -- 4 [label=2] 3 -- 5 [label=6] 4 -- 5 [label=3] } ``` ``` cpp= #include <iostream> #include <string> #include <sstream> #include <vector> #include <iterator> using namespace std; //--------------------------------------------------------------------------- // 測試資料 // // 第一行,一個整數 n 表示有幾個節點 // 剩下一直到結尾的每一行的 3 個整數都代表一條邊,格式為 v1 v2 w // v1 v2 代表線的兩個端點, // w 代表這條線的權重(或成本) // string input = "\ 6\n\ 0 1 4\n\ 0 2 2\n\ 1 2 1\n\ 1 3 5\n\ 2 3 8\n\ 2 4 10\n\ 3 4 2\n\ 3 5 6\n\ 4 5 3\n"; //--------------------------------------------------------------------------- struct Edge { int to, weight; }; typedef vector<Edge> Node; typedef vector<Node> Graph; vector<int> sssp_djkstra(Graph &g, int src) { vector<int> dist(g.size(), INT32_MAX); vector<bool> selected(g.size()); int remain_nodes = g.size(); dist[src] = 0; while (remain_nodes > 0) { int min_dist = INT32_MAX; int me = 0; // 找未展開的點中距離最小的 for (int i = 0; i < g.size(); i++) { if (!selected[i] && dist[i] < min_dist) { min_dist = dist[i]; me = i; } } int cur_dist = dist[me]; selected[me] = true; // 標記這點已被處理過 for (auto &e: g[me]) { // 鬆弛尚未處理過的相鄰點 if (!selected[e.to] && cur_dist + e.weight < dist[e.to]) { dist[e.to] = cur_dist + e.weight; } } remain_nodes--; } return dist; } int main() { stringstream sin(input); Graph G; int n, a, b, r; sin >> n; G.resize(n); // 有 n 個節點,從 0 號開始編號 while (sin >> a >> b >> r) { G[a].push_back({b, r}); G[b].push_back({a, r}); } // 印出從每一點當起點時,至各點的最短距離 for (int i = 0; i < G.size(); i++) { auto dist = sssp_djkstra(G, i); cout << i << ": "; copy(dist.begin(), dist.end(), ostream_iterator<int>(cout, " ")); cout << '\n'; } return 0; } ```