1. 程式人生 > >對dijkstra和Floyd演算法的理解

對dijkstra和Floyd演算法的理解

演算法的適應範圍

Floyed  演算法:

弗洛伊德演算法是解決任意兩點間的最短路徑的一種演算法,可以正確處理無向圖或有向圖或負權(但不可存在負權迴路)的最短路徑問題,同時也被用於計算有向圖的傳遞閉包。

Floyed演算法允許圖中有帶負權值邊,允許有迴路,但不允許有帶負權值邊的迴路。

Dijkstra演算法:

Dijkstra演算法只適用於正權圖的單源最短路。而對於存在權值為負的邊的圖,我們用的是SPFA(Shortest Path Faster Algorithm)演算法(佇列優化後的Bellman-Ford)。


ps:含負權的圖中最短路不一定存在。顯而易見,若一個圖中存在一個負環

,則最短路不存在。這是我們需要注意的一點。

演算法的具體操作

用演算法之前的建圖二者是一樣的,首先對map[][]進行初始化

for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
map[i][j]=(i==j?0:INF);

如果路是雙向的,就賦值map[i][j]=map[j][i]=權值,如果路是單向的,就賦值map[i][j]=權值。

Dijkstra演算法:

這個演算法和求最小生成樹的prim演算法很像(對prim演算法的理解 ),唯一不同的就是對距離陣列dis的更新。

dis[i]:x到n的最短路的距離。

void dijkstra(int x)
{
	int i,j;
	for(i=1;i<=n;i++)
		dis[i]=map[x][i];
	vis[x]=0;
	for(i=1;i<=n;i++)
	{
		int min=INF;
		int temp;
		for(j=1;j<=n;j++)
			if(vis[j]&&dis[j]<min)
			{
				min=dis[j];
				temp=j;
			}
		vis[temp]=0;
		for(j=1;j<=n;j++)
			if(vis[j]&&dis[temp]+map[temp][j]<dis[j])
				dis[j]=dis[temp]+map[temp][j];
	}
}

Floyd演算法:

map[i][j]:i到j的最短路的距離。

void floyd()
{
	int i,j,k;
	for(k=1;k<=n;k++)
	for(i=1;i<=n;i++)
	for(j=1;j<=n;j++)
	if(i!=k&&i!=j&&k!=j)
	map[i][j]=minn(map[i][j],map[i][k]+map[k][j]);		
}