一、算法介绍
Dijkstra算法用于求解单源最短路径问题,但是只限于非负权值的边。和Bellman-Ford想比,Dijkstra算法更稳定,复杂度更低一些。
二、伪代码
引自维基百科
1 function Dijkstra(G, w, s)
2 for each vertex v in V[G] // 初始化
3 d[v] := infinity // 將各點的已知最短距離先設成無窮大
4 previous[v] := undefined // 各点的已知最短路径上的前趋都未知
5 d[s] := 0 // 因为出发点到出发点间不需移动任何距离,所以可以直接将s到s的最小距离设为0
6 S := empty set
7 Q := set of all vertices
8 while Q is not an empty set // Dijkstra演算法主體
9 u := Extract_Min(Q)
10 S.append(u)
11 for each edge outgoing from u as (u,v)
12 if d[v] > d[u] + w(u,v) // 拓展边(u,v)。w(u,v)为从u到v的路径长度。
13 d[v] := d[u] + w(u,v) // 更新路径长度到更小的那个和值。
14 previous[v] := u // 紀錄前趨頂點
三、C++实现
#include <iostream>
#include <queue>
#include <cstring>
#include <vector>
using namespace std;
const int INF_NUM = 0x3f3f3f3f;
const int MAX_NUM = 2014;
typedef pair<int, int> pa;
vector<int> adj[MAX_NUM];
int source;
int vertexNum, edgeNum;
int map[MAX_NUM][MAX_NUM];
int dist[MAX_NUM], pred[MAX_NUM];
int visited[MAX_NUM];
priority_queue<pa, vector<pa>, greater<pa> > q;
int dijkstra()
{
for(int i = 1; i <= vertexNum; ++ i)
{
dist[i] = INF_NUM;
pred[i] = -1;
visited[i] = false;
}
dist[source] = 0;
q.push(make_pair(dist[source], source));
while(!q.empty())
{
pa tmp = q.top();
q.pop();
int u = tmp.second;
int d = tmp.first;
if(visited[u])
continue;
visited[u] = true;
int len = adj[u].size();
for(int i = 0; i < len; ++ i)
{
int v = adj[u][i];
if(dist[v] > d + map[u][v])
{
dist[v] = d + map[u][v];
pred[v] = u;
q.push(make_pair(dist[v], v));
}
}
}
}
void print()
{
for(int i = 1; i <= vertexNum; ++ i)
cout << dist[i] << " ";
cout << endl;
}
int main()
{
cin >> vertexNum >> edgeNum >> source;
int u, v, w;
for(int i = 0; i < edgeNum; ++ i)
{
cin >> u >> v >> w;
adj[u].push_back(v);
map[u][v] = map[v][u] = w;
}
dijkstra();
print();
return 0;
}
四、测试样例
样例输入
6 9 1
1 2 7
1 3 9
1 6 14
2 3 10
2 4 15
3 4 11
3 6 2
4 5 6
5 6 9
样例输出
0 7 9 20 26 11