dijkstre heap 用STL優先佇列優化

2021-06-16 13:11:55 字數 1463 閱讀 6563

大家說道dijkstra就不得不提它的heap優化。但是具體怎麼實現呢?

c++ stl提供了priority_queue, 支援push,top,pop操作。但是光靠這三個函式還不足以實現dijkstra的優化。

回想dijkstra演算法中,for(1..v)的大迴圈內,每次在unknown的集合中找到dist陣列裡最小的那個,從unknown集合中刪除該結點。樸素實現需要o(v)的時間,而用堆可以用o(log(v))的時間找到。然而,光找到還沒完,找到之後要鬆弛所有與他相鄰的unknown的結點(known的結點已經都是最短路了)。注意到如果要用堆實現優化,堆中儲存的結點的priority值應當是圖中該店當前的離source的距離。然而鬆弛操作會更新該距離,這就意味著我們要到堆內部找到這個結點的位置,更新距離,再維護堆。而堆是不提供檢索功能的,找到乙個結點需要o(v),完全糟蹋了o(log v)的優化了。更何況stl的priority_queue沒有辦法去接觸內部的資料了。

其實,有乙個可行的解決方案:一旦某個結點被更新了距離,一律但當成新結點加進堆裡。這樣會造成乙個乙個問題:乙個圖中的結點可能在堆中可能同時會存在好幾個。但是這個不影響結果:先出堆的一定是距離最小的那個結點。其他的結點出堆的時候圖裡面的對應結點一定已經在known的集合了,到時候直接無視掉彈出來的已經known的結點,繼續彈下乙個,知道彈出乙個unknown的結點為止。

這個做法最壞可能會讓堆的高度加倍,然是任然不影響o(log n)的複雜度。不過具體的複雜度計算貌似不那麼簡單……不過實踐證明速度確實有了很大提高,尤其是對於稀疏圖。

這種實現用stl的priority_queue也能完成,程式也只是在*****的dijkstra上加幾行,價效比不錯。

而真正的dijkstra+heap也是可以實現的。問題的關鍵集中在 reduce_to(int id,int value) 的操作。這要求我們自己實現乙個堆。堆的結點需要儲存2個資料,乙個是對應圖中結點的標號id,乙個是對應圖中結點的距離dist。而要支援reduce,我們需要乙個對映location,使得location[id]=要找的結點在堆中的位置,這個可以用陣列實現。需要注意的是,在維護堆的同時,也需要維護location對映。其實只要在維護堆的**裡稍作修改就能實現了,比想象的要簡單。

#include #include #define infinity 1000000000

using namespace std;

long g[1005][1005],d[1005];

char visited[1005];

struct vexnode

for(i=1;ic) //去重邊,只儲存最小的權值

g[e][s]=c;

}dijstra(n,kiki);

scanf("%d",&w);

peintf("%d\n",d[w]);

}return 0;

}

用ST官方例程測usart

面對的問題 1.晶元引腳不對應 2.stm32f40 41 stm32f40 41 sct 7 error l6235e more than one section matches selector cannot.3.大意是 systemint沒有定義 昨天沒來得及記錄,隔了一天寫了第三點 1.晶元...

st語言 陣列的常用方法 ST語言

st 語言學習心得 一 工程的簡介和建立工程 1.工程檔案的結 工程檔案的字尾名為 pro,在新工程中建立的第乙個程式結構單元 program organization unit 將被自動命名為 plc prg 這個程式結構單元就類似於 c語言中的主程式。在 plc prg 中可以呼叫各種函式及功能...

演算法 ST表

想學習一下lca倍增,先 水乙個黃題 學一下st表 這是乙個運用倍增思想,通過動態規劃來計算區間最值的演算法 求出區間最值 回答詢問 求出區間最值 用 f i j 來儲存從第 j 個點開始,向後 2 i 1 個點 共 2 i 個點 中的最值 包括本身 利用二分法的思想,將區間 j,j 2 i 1 平...