Dijkstra算法詳解

算法解決的是有向圖中單個源點到其他頂點的最短路徑問題,其主要特點是每次迭代時選擇的下一個頂點是標記點之外距離源點最近的頂點。但由於dijkstra算法主要計算從源點到其他所有點的最短路徑,所以算法的效率較低。

1.定義概覽
Dijkstra(迪傑斯特拉)算法是典型的單源最短路徑算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點爲中心向外層層擴展,直到擴展到終點爲止。Dijkstra算法是很有代表性的最短路徑算法,在很多專業課程中都作爲基本內容有詳細的介紹,如數據結構,圖論,運籌學等等。注意該算法要求圖中不存在負權邊。
問題描述:在無向圖 G=(V,E) 中,假設每條邊 E[i] 的長度爲 w[i],找到由頂點 V0 到其餘各點的最短路徑。(單源最短路徑)

2.算法描述
1)算法思想:設G=(V,E)是一個帶權有向圖,把圖中頂點集合V分成兩組,第一組爲已求出最短路徑的頂點集合(用S表示,初始時S中只有一個源點,以後每求得一條最短路徑 , 就將加入到集合S中,直到全部頂點都加入到S中,算法就結束了),第二組爲其餘未確定最短路徑的頂點集合(用U表示),按最短路徑長度的遞增次序依次把第二組的頂點加入S中。在加入的過程中,總保持從源點v到S中各頂點的最短路徑長度不大於從源點v到U中任何頂點的最短路徑長度。此外,每個頂點對應一個距離,S中的頂點的距離就是從v到此頂點的最短路徑長度,U中的頂點的距離,是從v到此頂點只包括S中的頂點爲中間頂點的當前最短路徑長度。
2)算法步驟:
a.初始時,S只包含源點,即S={v},v的距離爲0。U包含除v外的其他頂點,即:U={其餘頂點},若v與U中頂點u有邊,則<u,v>正常有權值,若u不是v的出邊鄰接點,則<u,v>權值爲∞。
b.從U中選取一個距離v最小的頂點k,把k,加入S中(該選定的距離就是v到k的最短路徑長度)。
c.以k爲新考慮的中間點,修改U中各頂點的距離;若從源點v到頂點u的距離(經過頂點k)比原來距離(不經過頂點k)短,則修改頂點u的距離值,修改後的距離值的頂點k的距離加上邊上的權。d.重複步驟b和c直到所有頂點都包含在S中。

4.算法實例
先給出一個無向圖


用Dijkstra算法找出以A爲起點的單源最短路徑步驟如下


dijkstra算法的流程圖如下所示:


#include <iostream>
using namespace std;
#define inf 1<<29
#define MAXV 1005
int map[MAXV][MAXV];
int n,m;
void dijkstra(){
	int i,j,min,v;
	int d[MAXV];
	bool vis[MAXV];

	for(i=1;i<=n;i++){
		vis[i]=0;
		d[i]=map[1][i];
	}
for(i=1;i<=n;i++){
		min=inf;
		for(j=1;j<=n;j++)
			if(!vis[j] && d[j]>map[v][j]+d[v]){
				v=j;
				min=d[j];
			}
vis[v]=1;

		for(j=1;j<=n;j++)
			if(!vis[j] && d[j]>map[v][j]+d[v])
				d[j]=map[v][j]+d[v];
	}
	printf("%d\n",d[n]);
}

int main(){
	int i,j,a,b,c;
	while(~scanf("%d%d",&m,&n)){
		
for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
				if(i==j)
					map[i][i]=0;
				else map[i][j]=map[j][i]=inf;
		
		for(i=1;i<=m;i++){
			scanf("%d%d%d",&a,&b,&c);
			if(map[a][b]>c) map[a][b]=map[b][a]=c;
		}
		dijkstra();
	}
	return 0;
}



發佈了24 篇原創文章 · 獲贊 28 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章