顧名思義就是尋找乙個源點到其它的點的最短路,暴力的dfs或者bfs就不說了,下面講講幾種單源最短路的演算法。
這個演算法的實質就是利用bfs,我們先將源點到源點的距離設定為0,到其它的距離設定為無窮大(一般0x7fffffff),然後將源點加入佇列,用隊首的點去bfs,更新它能到達且能更新的的點,然後將未進入佇列的點加入佇列以備後續更新使用,然後將已經出隊的點標記消掉,不斷這樣進行這個操作(這個也就是鬆弛操作),最後無法再更新任何乙個點時,隊列為空,最短路也就找完了,理論複雜度為o(
kn)'>o(k
n)o(
kn),
k'>k
k為進隊次數,一般k≤
'>k≤k
≤常數。
這個演算法在一般的圖和隨機圖上面執行效果良好,但是在一些精心構造的圖上面就會卡到複雜度上限o(
nm)'>o(n
m)o(
nm)(每個點進隊m次)。
下面介紹另一種演算法。
這個演算法同樣是用bfs,每次找到距離源點最近的且未被用過的點,然後拿它去更新其它點,而這個點以後再也不會被更新到(除非有負環,那麼普通的dijistra就無法使用),這樣每個點只會用來更新一次其它點,每次尋找最近的點暴力複雜度為o(
n)'>o(n
)o(n
),然後更新的複雜度為它的度數(一般看作常數,除非菊花圖),所以複雜度總的來說為o(
n2)'>o(n
2)o(
n2)。
我們發現上述的演算法中,有乙個尋找最近點的o(
n)'>o(n
)o(n
),可以拿乙個資料結構維護,將o(
n)'>o(n
)o(n
)降到o(
logn
)'>o(l
ogn)
o(lo
gn),那麼維護最小值我們可以簡單的使用堆(自己手打或者stl的優先佇列),那麼該演算法就被優化到了o(
nlog
n)'>o(n
logn
)o(n
logn
),雖然一般圖和隨機圖跑的沒有sfpa快,但是在精心構造的圖上面,它複雜度的優秀性就體現出來了。(noi2018的day1t1可以說明)
多源最短路,就是求圖上的每乙個點到其它點的最短距離,樸素簡單的想法就是跑
n'>n
n遍單源最短路演算法,但是這裡還有其它的演算法可以解決這個問題。
這個演算法實質上是利用了動態規劃,dp的思想,我們定義如下狀態f[
i][j
]'>f[i
][j]
f[i]
[j],表示i⇒
j'>i⇒j
i⇒j的最短路長度,然後我們列舉乙個中轉點
k'>k
k,用它去不斷更新其它情況,轉移方程為f[
i][j
]=mi
n(f[
i][j
],f[
i][k
]+f[
k][j
])'>f[i
][j]
=min
(f[i
][j]
,f[i
][k]
+f[k
][j]
)f[i
][j]
=min
(f[i
][j]
,f[i
][k]
+f[k
][j]
)。這樣n3
'>n3n
3就可以求出多源最短路。(其實似乎跑
n'>n
n邊dijistra+堆優化好像才o(
n2lo
gn)'>o(n
2log
n)o(
n2lo
gn)的複雜度,不過floyd的常數明顯較小)。
這個演算法還有個用途,其實從它的轉移上都可以看出,我們可以求必須經過某個點的多源最短路,這時就不用列舉中轉點,而是已知中轉點,然後去更新答案,複雜度為o(
n2)'>o(n
2)o(
n2)。
a-star(a*)啟發式搜尋演算法,原理是dfs時利用乙個估計函式來剪枝。
後面待更新完善……
最短路演算法總結
1.floyd演算法 n 3複雜度 基本思想 開始設集合s的初始狀態為空,然後依次將0,1,n 1定點加入,同時用d i j 儲存從i到j,僅經過s中的定點的最短路徑,在初始時刻,d i j a i j 中間不經過任何節點,然後依次向s中插入節點,並進行如下更新 d k i j min 還可以使用乙...
最短路演算法總結
藉著usaco 3.26搞了幾天最短路。不得不說usaco真是菜鳥學習演算法的利器啊,有資料可以查錯。題上是乙個800 800的稀疏圖,需要求全源最短路 先用floyd試了一下。畢竟就三行,很好寫。時間o n3 裸交第九個點果然tle了,不過看題解有人水過了 就把邏輯語言改了一下,無向圖時間又可以優...
最短路演算法總結
dijkstra演算法 dijkstra 迪傑斯特拉 演算法是典型的單源最短路徑演算法,用於計算乙個節點到其他所有節點的最短路徑。最常見的問題就是 給你一張地圖,讓你求出指定的點到其餘各定點的最短路徑。演算法核心 每次找到離源點最近的乙個頂點,然後以該頂點為中心進行擴充套件,最終的到源點到其餘所有點...