圖論-Dijkstra堆優化
阿新 • • 發佈:2019-01-28
之前已經寫過樸素的Dijkstra了:
int Dijkstra(int x) { int min, k; for(int i=1; i<=n; i++) d[i] = a[x][i]; d[x] = 0; InS[x] = true; for(int i=1; i<=n-1; i++) { min = 1e9; for(int j=1; j<=n; j++) if(min > d[j] && !InS[j]) min = d[k=j]; InS[k] = true; for(int j=1; j<=n; j++) if(d[j] > d[k]+a[k][j]) d[j] = d[k] + a[k][j]; } for(int i=1; i<=n; i++) cout << d[i] << " "; }
下面是基於vector陣列的堆優化Dijkstra
#include <iostream> #include <queue> #include <cstring> #include <cstdio> using namespace std; struct Edge { int from, to, dis; Edge(int u, int v, int w) : from(u), to(v), dis(w) {} }; struct HeapNode { int d, u; bool operator <(const HeapNode h) const { return d > h.d; } }; #define MAXN 10010 struct Dijkstra { int n, m; vector<Edge> edges; //所有邊 vector<int> G[MAXN]; //以i為起點的所有邊 bool done[MAXN]; int d[MAXN]; int p[MAXN]; //記錄上一條弧 void init(int n) { this -> n = n; for(int i=1; i<=n; i++) G[i].clear(); edges.clear(); } void Add(int u, int v, int d) { edges.push_back(Edge(u, v, d)); m = edges.size(); G[u].push_back(m-1); } void dijkstra(int s) { priority_queue<HeapNode> Q; for(int i=1; i<=n; i++) d[i] = 2147483647; d[s] = 0; memset(done, 0, sizeof(done)); Q.push((HeapNode) { 0, s }); while(!Q.empty()) { HeapNode x = Q.top(); Q.pop(); int u = x.u; if(done[u]) continue; done[u] = true; for(int i=0; i<G[u].size(); i++) { Edge e = edges[G[u][i]]; if(d[e.to] > d[u] + e.dis) { d[e.to] = d[u] + e.dis; p[e.to] = G[u][i]; //記錄最短路徑 Q.push((HeapNode) { d[e.to], e.to }); } } } } void Print_Path(int x) { //源點到x的最短路徑 if(x == 0) return; Print_Path(p[x]); printf("%d ->", x); } } Dijk; int main() { int n, m, u, v, w, s; scanf("%d%d%d", &n, &m, &s); Dijk.init(n); for(int i=1; i<=m; i++) { scanf("%d%d%d", &u, &v, &w); Dijk.Add(u, v, w); } Dijk.dijkstra(s); for(int i=1; i<=n; i++) printf("%d ", Dijk.d[i]); return 0; }