Dijkstra求最短路與次短路

2021-07-02 02:49:56 字數 1897 閱讀 5557

花了乙個晚上加上午兩節課的時間來思考這個問題,一開始進了個誤區,後來發現不對,找到了正確思路,現在來做個總結

最短路:

假設有如下 無向圖:

每條邊有權,要求從a到g的最短路,設陣列d[i]用來記錄每個點到a的最短路,d用來記錄權值d[0]=0。先來說一下我一開始的誤區,在看了一些介紹這個演算法的文章後我大概知道了是要一步一步來更新每個點的最小值。於是我是這樣想的從a到b遍歷,a到a的距離是0,然後是b,d[1]=d[0][1]=2,然後是c,d[2]=min(d[0][2], d[1]+d[1][2])=5,接下來是d,d[3]=min(d[1]+d[1][3], d[2]+d[2][3]),我用圖來解釋這個過程:

最後結果是的d[6]=17,但實際上問題在e和f上已經出現了,由於我們先算的是e,在這時陣列裡f的距離還是無窮大,所以e只能從b得到乙個2,再加上be=10就是12。但算過f後發現,e的最短距離應該是f的8加上ef=3,結果是11,於是g的最短距離應該是11+5=16。問題就在於我們按abcdefg的順序依次簡單地求當前點的最短距離時,每個點的距離只能更新一次,無法從後續計算中得到該點更近的距離。這種方法中」當前點「是未求值的點,而正確的做法應該把」當前點「定為已求過的點。也就是說,我們要做的是從該點出發求臨近點的最小值,而不是站在該點,用已求過值的臨近點來求該點的值。

正確的過程應該是這樣,計算每個點時都要用這個轉移方程d[i]=min(d[i], d[j]+d[i][j]),其中j是當前點,i是與j相連的點:

從a開始,a與b,c相連,更新b,c,d[1]=2, d[2]=5;

轉到b,b與cde相連,d[2]=min(d[2], d[1]+d[2][1])=5,同理,d[3]=7, d[4]=12

…………

到f時,f與deg相連,所以在更新e的時候就會有d[4]=min(d[4], d[5]+d[5][4])=11;

這樣做就可以用在e之後的f來更新e的值。

這一過程可以直接將d[i]放到迴圈裡實現,也可以用優先佇列,將(d[i], i)入列。當從某個點j求得的d[i]大於陣列中已有的d[i]時,就不入列。這個優先佇列的過程在紙上畫一畫就很清楚了。

忘了說了,在轉移到下乙個點時必須轉移到d[i]最小的點,這個條件非常重要!

次短路:

接下來是次短路。次短路的做法和最短路幾乎一模一樣。在過程中同時記錄每個點的最短路和次短路,然後用同樣的方法更新每個點的值。要注意的就是計算與當前點相鄰點的次短路時需要同時用到該點的最短路和次短路,也就是要求三個值的最小值:min(d2[i], d[j]+d[i][j], d2[j]+d[i][j]),其中陣列d2[i]就是每點的次短路。要注意的是要先求最短路再求次短路,保證最短路小於次短路。

Dijkstra求最短路

題目鏈結 給定乙個n個點m條邊的有向圖,圖中可能存在重邊和自環,所有邊權均為正值。請你求出1號點到n號點的最短距離,如果無法從1號點走到n號點,則輸出 1。輸入格式 第一行包含整數n和m。接下來m行每行包含三個整數x,y,z,表示存在一條從點x到點y的有向邊,邊長為z。輸出格式 輸出乙個整數,表示1...

Dijkstra求最短路

題目鏈結 給定乙個n個點m條邊的有向圖,圖中可能存在重邊和自環,所有邊權均為非負值。請你求出1號點到n號點的最短距離,如果無法從1號點走到n號點,則輸出 1。輸入格式 第一行包含整數n和m。接下來m行每行包含三個整數x,y,z,表示存在一條從點x到點y的有向邊,邊長為z。輸出格式 輸出乙個整數,表示...

Dijkstra求最短路

如果圖中存在負權邊,則不要使用 dijkstra 來求最短路。如果題目中表明所給的圖存在重邊與自環。在求最短路徑的問題中,如果自環邊權重是 正數,顯然它不會出現在最短路徑中。如果自環邊是 負數,則需要考慮出現在最短路中。如果是稠密圖,使用了鄰接矩陣來存邊,則因為求最短路,所以我們對於重邊,只需要儲存...