1. 程式人生 > >最短路徑(Dijkstra and Floyd)

最短路徑(Dijkstra and Floyd)

看了一個下午的資料才明白迪傑斯特拉演算法,關鍵是網上的好多解釋太拗口了。弗洛伊達好明白。

迪傑斯特演算法主要思想就是把頂點分為兩組,一組是求出最短路徑的,另一組是沒求出的(第二組)。然後選擇從源點到第二組中某個頂點路徑最短的那個點,把它加入第一組(其實這個時候以那個點的最短路徑就已經確定了),一直這樣下去,直到加入了所有的點(i=1~n)。

為什麼說加入了第一組就已經確定了最短路徑了? 這樣想,從源點到這個點的路徑通過比較後確定是最短的,因為圖無負的權值,那就不可能找到任何一箇中轉點使得路徑更短了。

其實要有圖就更好理解,為了不侵權就不放圖了。

程式碼不重要,關鍵要理解這個過程。

for(int i=1; i<n;i++)

{

min=MAXINT;

for(int w=0;w<n;w++)  //這個迴圈就是在找到第二組的某個點v,要讓以它為終點的路徑最短。

if(!s[w]&&D[w]<min) //!s[w] 就是說這個點在第二組

{

v=w; min=D[w];

}

s[v]=true;  //找到了那個點v,把它加入第一組

for(int w=0;w<n;w++)  //更新一邊從源點到第二組每個點的路徑,這個時候要考慮以v為中轉點。

if(!s[w]&&(D[v]+G.arcs[v][w]<D[w])

{

D[w]=D[v]+G.arcs[v][w];

}

}

寫完這個過程之後,感覺思路更清晰了一點。

任意2個點的最短路徑,可以反覆用迪傑斯特,但用floyd會更簡潔。

主要思想是一直加點。

for(int k=0;k<n;k++)

for(int i=0;i<n;i++)

for(int j=0;j<n;j++)

if(D[i][k]+D[k][j]<D[i][j])

{

D[i][j]=D[i][k]+D[k][j];

}

呃,我其實在想,其實用floyd來實現迪傑斯特那樣的問題也行吧,是不是說把第二個for迴圈去掉,再改一改就行了呢?現在有點忙,自己還不太想去弄吐舌頭