最短路徑(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迴圈去掉,再改一改就行了呢?現在有點忙,自己還不太想去弄。