一:簡介
這個算法用於解決圖中單源最短路徑問題。所謂單源節點是指給定源節點,求圖中其它節點到此源節點的最短路徑。如下圖所示:給定源節點a,求節點b到a的最短距離。
(圖來自於參考資料2)那麼如何尋找?還是以上圖爲例:
1)初始化:設定除源節點以外的其它所有節點到源節點的距離爲INFINITE(一個很大的數),且這些節點都沒被處理過。
2)從源節點出發,更新相鄰節點(圖中爲2,3,6)到源節點的距離。然後在所有節點中選擇一個最段距離的點作爲當前節點。
3)標記當前節點爲done(表示已經被處理過),與步驟2類似,更新其相鄰節點的距離。(這些相鄰節點的距離更新也叫鬆弛,目的是讓它們與源節點的距離最小。因爲你是在當前最小距離的基礎上進行更新的,由於當前節點到源節點的距離已經是最小的了,那麼如果這些節點之前得到的距離比這個距離大的話,我們就更新它)。
4)步驟3做完以後,設置這個當前節點已被done,然後尋找下一個具有最小代價(cost)的點,作爲新的當前節點,重複步驟3.
5)如果最後檢測到目標節點時,其周圍所有的節點都已被處理,那麼目標節點與源節點的距離就是最小距離了。如果想看這個最小距離所經過的路徑,可以回溯,前提是你在步驟3裏面加入了當前節點的最優路徑前驅節點信息。
看文字描述顯得蒼白無力,你可以結合上圖,看下這個視頻:http://v.youku.com/v_show/id_XMjQyOTY1NDQw.html
(dijkstra演示),然後就清楚了。
我比較懶不想打字所以以上文字來源:
代碼原創
[http://www.cnblogs.com/wb-DarkHorse/archive/2013/03/12/2948467.html]
下面代碼是帶路徑的,其他的自己可以修改。
#include <iostream>
#include <cstring>
#include <stack>
using namespace std;
#define MAX 100
#define INF 0x3f3f3f3f
int dist[MAX], path[MAX];
struct MGraph
{
int edges[MAX][MAX];//鄰接矩陣,記錄的是兩點之間的距離,也就是權值
int n,e;//頂點數和邊數
}G;
void init() {
memset(G.edges, INF, sizeof(G.edges));//默認爲INF
}
void insert(int u, int v, int w) {
G.edges[u][v] = w;//
}
void printfPath(int path[], int a){
stack<int> s;
//這個循環以由葉子結點到根結點的順序將其入棧
while(path[a] != -1){
s.push(a);
a = path[a];
}
s.push(a);
while(!s.empty()){
cout << s.top() << " ";//打印棧頂元素,實現了頂點的逆序打印
s.pop();
}
cout << endl;
}
void Dijkstra(MGraph g, int v, int dist[], int path[]){ //頂點默認從0到n
int set[MAX], min, i, j, u;
//對各個數組進行初始化
for(i = 0; i < g.n; i++){
dist[i] = g.edges[v][i];
set[i] = 0;
if(g.edges[v][i] < INF){
path[i] = v;
}else{
path[i] = -1;
}
}
set[v] = 1;
path[v] = -1;
//初始化結束,關鍵操作開始
for(i = 0; i < g.n - 1; i++)
{
min = INF;//找到的點 目前最小
//這個循環每次從剩餘頂點中選出一個頂點,通往這個頂點的路徑在通往所有剩餘頂點的路徑中是長度最短的
for(j = 0; j < g.n; j++){
if(set[j] == 0 && dist[j] < min){
u = j;
min = dist[j];
}
}
set[u] = 1;//將選出的頂點併入最短路徑中
//這個循環以剛併入的頂點作爲中間點,對所有通往剩餘頂點的路徑進行檢測
for(j = 0; j < g.n; j++) {
//這個if判斷頂點u的加入是否會出現通往頂點j的更短的路徑,如果出現,則改變原來路徑及其長度,否則什麼都不做
if(set[j] == 0 && dist[u] + g.edges[u][j] < dist[j]){
dist[j] = dist[u] + g.edges[u][j];//更新路徑長度
path[j] = u;//更新路徑頂點
}
}
}
}
int main() {
init();
int n, m;//n個點,m條邊
int a, x, y, w;
cin >> m >> n;
G.e = m;
G.n = n;
for(int i = 0; i < m; i++){
cin >> x >> y >> w;
insert(x, y, w);
}
Dijkstra(G, 0, dist, path);
printfPath(path, 5);
for(int i = 0; i < n; i++) {
cout << dist[i] << " ";
}
return 0;
}
/*測試數據
12 7
0 1 4
0 2 6
0 3 6
1 4 7
1 2 1
2 4 6
2 5 4
3 2 2
3 5 5
4 6 6
5 4 1
5 6 8
*/