最短路算法 —— Dijkstra算法
阿新 • • 發佈:2018-08-24
math bool see namespace bsp 算法 鄰接矩陣 最短路徑 eat
用途:
解決單源最短路徑問題(已固定一個起點,求它到其他所有點的最短路問題)
算法核心(廣搜):
(1)確定的與起點相鄰的點的最短距離,再根據已確定最短距離的點更新其他與之相鄰的點的最短距離。
(2)之後的更新不需要再關心最短距離已確定的點
三種實現模板:
一、矩陣樸素版
二、vector簡單版
三、靜態鄰接表有點復雜版
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <deque> 5 #include <cstdio> 6#include <vector> 7 #include <queue> 8 #include <cmath> 9 #define INF 0x3f3f3f3f 10 using namespace std; 11 12 //鄰接矩陣 13 14 const int MAXN = 110; 15 int dis[MAXN]; 16 int e[MAXN][MAXN]; 17 bool vis[MAXN]; 18 int N, M; 19 20 void dij() 21 { 22 int p, mis; 23 for(int i = 1; i <= N; i++) 24 dis[i] = e[1][i]; 25 26 27 vis[1] = true; 28 dis[1] = 0; 29 for(int i = 1; i < N; i++) 30 { 31 mis = INF; 32 for(int j = 1; j <= N; j++) 33 { 34 if(!vis[j] && dis[j] < mis) 35 {36 mis = dis[j]; 37 p = j; 38 } 39 } 40 vis[p] = true; 41 42 for(int k = 1; k <= N; k++) 43 { 44 if(dis[k] > dis[p] + e[p][k] && !vis[k]) 45 dis[k] = dis[p] + e[p][k]; 46 } 47 } 48 } 49 50 void init() 51 { 52 for(int i = 1; i <= N; i++) 53 for(int j = 1; j <= N; j++) 54 if(i == j) e[i][j] = 0; 55 else e[i][j] = INF; 56 memset(vis, false, sizeof(vis)); 57 } 58 int main() 59 { 60 int a, b, c; 61 while(~scanf("%d%d", &N, &M)) 62 { 63 if(N == 0 && M == 0) break; 64 init(); 65 while(M--) 66 { 67 scanf("%d%d%d", &a, &b, &c); 68 e[a][b] = c; 69 e[b][a] = c; 70 } 71 72 dij(); 73 printf("%d\n", dis[N]); 74 } 75 76 return 0; 77 } 78 79 80 81 //vector 動態鄰接表 + 優先隊列 82 83 const int MAXN = 1e3 + 50; 84 struct edge 85 { 86 int to, cost; 87 edge(int vo = 0, int vt = 0): 88 to(vo),cost(vt){} 89 }; 90 91 vector<edge>G[MAXN]; 92 typedef pair<int, int>P; 93 int dis[MAXN]; 94 int N, M; 95 96 void init() 97 { 98 for(int i = 1; i <= N; i++) 99 { 100 G[i].clear(); 101 dis[i] = INF; 102 } 103 104 } 105 void Dijkstra(int s) 106 { 107 int u, v; 108 priority_queue<P, vector<P>, greater<P> > que; 109 que.push(P(0, s)); 110 dis[s] = 0; 111 112 while(!que.empty()) 113 { 114 P p = que.top(); que.pop(); 115 116 int u = p.second; 117 if(dis[u] < p.first) continue; 118 119 for(int i = 0; i < G[u].size(); i++) 120 { 121 edge v = G[u][i]; 122 if(dis[v.to] > dis[u] + v.cost) 123 { 124 dis[v.to] = dis[u] + v.cost; 125 que.push(P(dis[v.to], v.to)); 126 } 127 } 128 } 129 } 130 131 int main() 132 { 133 int u, v, c; 134 scanf("%d%d", &N, &M); 135 init(); 136 while(M--) 137 { 138 scanf("%d%d", &u, &v, &c); 139 G[u].push_back(edge(v, c)); 140 //G[v].push(edge(u, c)); 建無向圖 141 } 142 143 //see see 144 /* 145 for(int i = 1; i <= N; i++) 146 { 147 for(int j = 0; j < G[i].size(); j++) 148 printf("%d ", G[i][j].to); 149 puts(""); 150 } 151 */ 152 153 Dijkstra(1); 154 for(int i = 1; i <= N; i++) 155 printf("%d ", dis[i]); 156 puts(""); 157 158 return 0; 159 } 160 161 162 163 164 ///靜態鄰接表 + 優先隊列優化 165 166 const int MAXN = 1e3 + 50; 167 typedef pair<int, int> HeapNode; 168 struct edge 169 { 170 int v, nxt, w; 171 }G[MAXN*100]; 172 int head[MAXN], dis[MAXN]; 173 int N, M, cnt; 174 175 inline void init() 176 { 177 for(int i = 0; i <= N; i++) 178 head[i] = -1, dis[i] = INF; 179 cnt = 0; 180 } 181 182 inline void add(int from, int to, int we) 183 { 184 G[cnt].w = we; 185 G[cnt].v = to; 186 G[cnt].nxt = head[from]; 187 head[from] = cnt++; 188 } 189 190 void dij() 191 { 192 priority_queue<HeapNode, vector<HeapNode>, greater<HeapNode> > heap; 193 dis[1] = 0; 194 heap.push(make_pair(0, 1)); 195 while(!heap.empty()) 196 { 197 pair<int, int>T = heap.top(); 198 heap.pop(); 199 200 if(T.first != dis[T.second]) continue; 201 202 for(int i = head[T.second]; i != -1; i = G[i].nxt) 203 { 204 int v = G[i].v; 205 if(dis[v] > dis[T.second] + G[i].w) 206 { 207 dis[v] = dis[T.second] + G[i].w; 208 heap.push(make_pair(dis[v], v)); 209 } 210 } 211 } 212 } 213 214 int main() 215 { 216 int a, b, c; 217 while(~scanf("%d%d", &N, &M)) 218 { 219 if(N == 0 && M == 0) break; 220 init(); 221 while(M--) 222 { 223 scanf("%d%d%d", &a, &b, &c); 224 add(a, b, c); 225 add(b, a, c); 226 } 227 228 dij(); 229 printf("%d\n", dis[N]); 230 } 231 232 return 0; 233 }
最短路算法 —— Dijkstra算法