1. 程式人生 > >最短路徑 單源最短路徑Dijkstra(迪傑斯特拉)演算法 Floyd(弗洛伊德)演算法

最短路徑 單源最短路徑Dijkstra(迪傑斯特拉)演算法 Floyd(弗洛伊德)演算法

兩個演算法的主要思想都是鬆弛,就是兩點間的距離通過第三點來變短

比如   1->3=10     1->2=2   2->3=5    這樣你就可以通過2號點把1,3兩點的距離縮短為7

Dijkstra演算法被稱為單源最短路,意思就是隻能計算某個點到其他點的最短路,而Floyd演算法

可以計算各個點之間的最短路徑。

舉個例子:有1~6  6個點   Dijkstra只能計算1號(或者2、3....其中某一個)點到其他點的最短路徑

而Floyd演算法就可以直接把1->2   1->3 .......任意兩點之間的最短路都算出來

當然Floyd的時間複雜度是比Dijkstra高的。

首先來看Floyd演算法

for (k=1;k<=n;k++)
	for (i=1;i<=n;i++)
		for (j=1;j<=n;j++)
			if (e[i][j]>e[i][k]+e[k][j])
			e[i][j]=e[i][k]+e[k][j];

使用K點對i,j兩點進行縮短(鬆弛),當從 i 到 k 再從 k 到 j 的距離小於從 i 直接到 k 的距離是 i 到 j 的距離就被縮短。

最終的圖就是一個全部為最短路的圖

再看Dijkstra演算法  

首先來解釋一下什麼叫源,源其實就是起點,你想從哪一個點開始走的點。

單源最短就是單單這個點和其他各點的最短路。

因為是單源的所以我們就不必要設定一個二維陣列,可以設定一個一位陣列dis[],dis[i]表示的就是

源點到 i 的最短路徑。

先上程式碼: 

void dijkstra(){
	bool book[maxn];
	memset(book,0,sizeof(book));
	int m;
	for(int i=1;i<T;i++){
		int min=INF;
		for(int j=1;j<=T;j++){
			if(!book[j] && dis[j]<min){
				min=dis[j];
				m=j;
			}
		}
		book[m]=true;
		for(int k=1;k<=T;k++){
			if(dis[k]>dis[m]+e[m][k]) dis[k]=dis[m]+e[m][k];
		}
	}
	
}

主要思想就是:先找到一個和源點最近的點,這個點和源點之間肯定是最短路了(因為不可能通過第三個點進行鬆弛了(負權除外)),標記這個點已經找到它到源點最短路,然後通過這個點對其他各個點進行鬆弛。重複上述步驟,知道標記完所有的點。

                                                                                             完活!