Dijkstra算法
以poj 2387 为例
以邻接矩阵实现
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 const int SIZE = 1005; 8 const int inf = 10000000; 9 10 int vis[SIZE]; 11 int dist[SIZE]; 12 int cost[SIZE][SIZE]; 13 14 void init(int n) 15 { 16 int i,j; 17 18 for(i = 1; i <= n; i ++) 19 for(j = 1; j <= n; j ++) 20 cost[i][j] = inf; 21 } 22 23 void init() 24 { 25 int i,j; 26 27 for(i = 0; i < SIZE; i ++) 28 for(j = 0; j < SIZE; j ++) 29 cost[i][j] = inf; 30 } 31 32 int Dijkstra(int v,int n) 33 { 34 int u,w; 35 int i,j,k; 36 int min = inf; 37 38 39 for(i = 1; i <= n; i ++) 40 { 41 dist[i] = cost[v][i]; 42 vis[i] = 0; 43 } 44 dist[v] = 0; 45 vis[v] = 1; 46 47 for(k = 2; k < n; k ++) 48 { 49 min = inf; 50 for(i = 1; i <= n; i ++) 51 if(min > dist[i] && vis[i] == 0) 52 { 53 min = dist[i]; 54 u = i; 55 } 56 57 vis[u] = 1; 58 59 for(w = 1; w <= n; w ++) 60 if(vis[w] == 0 && dist[w] > dist[u] + cost[u][w]) 61 dist[w] = dist[u] + cost[u][w]; 62 63 } 64 65 return dist[n]; 66 } 67 68 int main() 69 { 70 int i,j,k; 71 int len; 72 int t,n; 73 int sp; 74 75 76 cin >> t >> n; 77 //init(n); 78 init(); 79 for(i = 1; i <= t; i ++) 80 { 81 cin >> j >> k; 82 cin >> len; 83 if(cost[j][k] > len) 84 { 85 cost[j][k] = len; 86 cost[k][j] = cost[j][k]; 87 } 88 } 89 90 sp = Dijkstra(1,n); 91 92 cout << sp << endl; 93 94 return 0; 95 }
通过邻接表对空间进行优化
4 #include <stdio.h> 5 #include <iostream> 6 #include <algorithm> 7 #include <vector> 8 using namespace std; 9 10 const int SIZE = 1005; 11 const int inf = 10000000; 12 struct Node{ 13 int next,len; 14 Node(int a = 0, int b = inf):next(a),len(b){} 15 }; 16 vector<Node>cost[SIZE]; 17 vector<bool> vis(SIZE, false); 18 vector<int> dist(SIZE, inf); 19 20 int Dijkstra(int v, int n) 21 { 22 int i,j; 23 int u,w; 24 int min; 25 26 for(i = 0; i < cost[v].size(); i ++) 27 if(dist[cost[v][i].next] > cost[v][i].len) 28 { 29 dist[cost[v][i].next] = cost[v][i].len; 30 } 31 dist[v] = 0; 32 vis[v] = true; 33 34 for(i = 2; i < n; i ++) 35 { 36 min = inf; 37 for(j = 1; j <= n; j ++) 38 if(!vis[j] && dist[j] < min) 39 { 40 min = dist[j]; 41 u = j; 42 } 43 vis[u] = true; 44 45 for(j = 0; j < cost[u].size(); j ++) 46 if(!vis[cost[u][j].next] && dist[cost[u][j].next] > dist[u] + cost[u][j].len) 47 dist[cost[u][j].next] = dist[u] + cost[u][j].len; 48 } 49 50 return dist[n]; 51 } 52 53 int main() 54 { 55 int t,n; 56 int s,e; 57 int len; 58 int sp; 59 60 cin >> t >> n; 61 62 for(int i = 1; i <= t; i ++) 63 { 64 cin >> s >> e >> len; 65 cost[s].push_back(Node(e,len)); 66 cost[e].push_back(Node(s,len)); 67 } 68 69 sp = Dijkstra(1,n); 70 71 cout << sp << endl; 72 73 return 0; 74 }
最后,优先队列优化Dijkstra
1 #include<queue> 2 #include<vector> 3 #include<stdio.h> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 8 const int Size = 1005; 9 const int inf = 10000000; 10 11 struct Node{ 12 int end; 13 int len; 14 Node(int a = 0, int b = inf):end(a),len(b){} 15 bool operator < (const Node& a) const 16 { 17 return this -> len > a.len; 18 } 19 }; 20 21 vector<Node> cost[Size]; 22 int main() 23 { 24 int t,n; 25 int i,j; 26 int s,e,len; 27 28 scanf("%d%d",&t,&n); 29 30 for(i = 1; i <= t; i ++) 31 { 32 scanf("%d%d%d",&s,&e,&len); 33 cost[s].push_back(Node(e,len)); 34 cost[e].push_back(Node(s,len)); 35 } 36 37 vector<bool> vis(n + 1,false); 38 vector<int> dist(n + 1,inf); 39 priority_queue<Node> Queue; 40 41 for(i = 0; i < cost[1].size(); i ++) 42 { 43 dist[cost[1][i].end] = cost[1][i].len; 44 Queue.push(cost[1][i]); 45 } 46 vis[1] = true; 47 dist[1] = 0; 48 49 for(i = 2; i <=n; i ++) 50 { 51 while(vis[Queue.top().end]) 52 Queue.pop(); 53 Node ntemp = Queue.top(); 54 if(ntemp.end == n || ntemp.len == inf) 55 { 56 dist[n] = ntemp.len; 57 break; 58 } 59 Queue.pop(); 60 vis[ntemp.end] = true; 61 62 for(j = 0; j < cost[ntemp.end].size(); j ++) 63 { 64 int en = cost[ntemp.end][j].end; 65 int le = ntemp.len + cost[ntemp.end][j].len; 66 if(!vis[en] && dist[en] > le) 67 { 68 dist[en] = le; 69 Queue.push(Node(en, le)); 70 } 71 } 72 } 73 74 printf("%d\n",dist[n]); 75 76 return 0; 77 }
个人观点,Dijkstra的核心思想是贪心,从源点开始,搜寻周围的点,找到最近点,然后将最近点附近的点进行松弛,对于松弛操作,相当于一次次的记忆化的操作,然后再从其余临近点中找到一个新的最小点,直到所有点都操作一遍。而对于算法的优先队列优化,是基于查询已有的与源点存在相邻或相邻的已搜寻到的相邻关系中点的最小值,然后进行松弛更新,也就是说给周围所有点搜寻路径并将最短路径值不断存储更新,从而找到最短路。