一.定義:從起點s出發到達目標t的第k小的路徑
二.樸素演算法:
直接bfs(帶優先佇列),當目標節點t第k次出佇列時,即為所求.
解釋:bfs第一次搜到t點時,即為最短距離,那麼當第二次搜到呢?不用說,是次短路
rt. : 次短路 節點(距離) s:1 t:6
出佇列 佇列內元素
1(0) 2(7) 3(9) 6(14)
2(7) 3(9) 6(14) 1(14) 3(17) 4(22)
3(9) 6(11) 6(14) 1(14) 3(17) 1(18) 2(19) 4(20) 4(22)
6(11) 3(13) 6(14) 1(14) 3(17) 1(18) 2(19) 4(20) 5(20) 4(22) 1(25)
3(13) 6(14) 6(15) 1(14) 3(17) 1(18) 2(19) 4(20) 5(20) 4(22) 1(22) 2(23) 4(25) 1(25)
6(14) end
三.優化演算法—a*演算法
1)作為bfs的優化,a*是十分強大的.簡單的來說它就是確定了較為準確優先順序的bfs(帶優先佇列).
較為準確的優先順序—評估函式:f(p)=g(p)+h(p)
—a*演算法的核心.此函式標準解讀為:評估代價=起點至p點的實際代價(g)+p至s的預計代價(h).在此題中可理解為:評估距離=已走過的距離(g)+p至s的預計距離(h)
—關於h():令實際代價為h』() ,則:
1.h()<h』() 會導致估計不準確,從而wa
2.h()>=h』() h()-h』() 越小,速度越快.大則反之
2)結合上述規律,要盡快求出ans,保證演算法速度,就要使h()盡可能與h』()相近. 廢話當然,略微思考就會發現h()』是可以直接預處理出來的: 將圖反向後求一遍單源最短路即可.
3)步驟:
1.將圖反向求一遍spfa / dijkstra ,預處理出h()
2.bfs(a*),記錄出佇列次數,後進行拓展
3. 若t的出佇列次數等於k,得出ans,終止迴圈
四.注意點
1.求最短路時邊反向
2.當s==t時,第一次dis=0時不算在內
3.注意"判斷到達終點"的位置,必須從優先佇列中取出後判斷
學習筆記 k短路
a 我已經忘了怎麼寫了,反正n 30,m 1000都能卡掉。正解 可持久化左偏樹 堆維護可能集合 原 概括 結論 1.t為根求最短路樹t,定義p 為路徑s t的路徑p和t沒有交集的部分,p 和p都是有序邊集 對於p 中相鄰邊一定存在tail和head的祖先後代關係 或者重合 2.新定義邊的代價 di...
K短路 學習筆記
k短路,顧名思義,是讓你求從 s 到 t 的第 k 短的路。暴力當然不可取,那麼我們有什麼演算法可以解決這個問題?首先,我們要維護乙個堆。struct node priority queue q 這個堆是用來幹什麼的?這時候要提到一種新演算法 a 演算法。估價函式 f i g i h i 其中,g ...
第K短路 嚴格第K短路
所謂k短路,就是從s到t的第k短的路,第1短就是最短路。如何求第k短呢?有一種簡單的方法是廣度優先搜尋,記錄t出佇列的次數,當t第k次出佇列時,就是第k短路了。但點數過大時,入佇列的節點過多,時間和空間複雜度都較高。a 是在搜尋中常用的優化,一種啟發式搜尋。簡單的說,它可以用公式表示為f n g n...