最短路總結

2022-03-18 08:06:54 字數 1599 閱讀 4403

背景:

只是想來備份一下最近的**,順便總結一下三種最短路演算法的應用。

基礎**:

dijkstra:

1

struct nd};

2int d[maxn]; bool vis[maxn]; priority_queueq;

3void dijkstra(int

s));

5while(!q.empty()));9}

10}11 }

spfa(bfs+slf):

1 ll d[maxn]; bool inq[maxn]; dequeq;

2ll spfa()12}

13}14return

d[n];

15 }

spfa(dfs):

1

bool ins[maxn],f; double

d[maxn];

2void dfs(int

x) d[es[i].t]=d[x]+es[i].w; dfs(es[i].t);8}

9}10 ins[x]=0;11

}12bool

spfa() return1;

15 }

floyd:

1 inc(k,1,n)inc(i,1,n)inc(j,1,n)if(map[i][k]+map[k][j]

比較:dijkstra:

本演算法的優點就是快,沒有什麼一定需要其解決的問題,且只能處理正權邊及求最短路(不能求最長路)。複雜度為o(mlog2n)不過常數會稍大。

spfa:

優點是可以處理負權邊以及判負環,當不用判負環時bfs+slf(雙端佇列優化)的最壞複雜度是o(nm),但是常數很小,有時快過dijkstra。當需要判負環時bfs+slf複雜度經常會達到最壞複雜度,這時候用dfs寫法會明顯快很多,因為在不連通圖中判負環需要每個點都作為源點跑一次。

floyd:

優點是短,可以用一行求出兩兩點的最短路,複雜度o(n3)且常數很小。

常見模型:

差分約束系統:

n個數,知道他們兩兩之間形如ai-aj≥c,ai-aj≤c的關係,求n個數最小/最大是多少。解法:如果是求最大值,則將所有限制條件轉化為為≤,將得到的i和j連邊,權值為c並跑最短路,因為得到的是滿足條件的最大值;如果是求最小值,則將所有限制條件設定為≥,將得到的i和j連邊,權值為c並跑最長路,因為得到的是滿足條件的最小值。

01分數規劃:

n點m邊有向圖,點有點權,邊有邊權,從某點出發,走一些路使得經過的點權和除以(浮點數除法)邊權和最大或最小,求這個小數(保留兩位)。解法:假設需要所求小數最大,那麼二分這個數,然後將所有邊的邊權改為分母(需要最小化的部分)*二分的數-分子(需要最大化的部分),然後判負環。如果有,說明解合法,否則解不合法。最後把下界輸出。如果需要所求小數最小,則把邊權改為分子(需要最大化的部分)-分母(需要最小化的部分)*二分的數,同時改變範圍縮小的方向。

倍增floyd:

從s到t,要求剛好經過k條邊,求最短路。解法:把用floyd的方式對兩個鄰接矩陣進行合併定義成乙個運算,則答案為初始矩陣與自己做k次運算得到的結果。而該運算符合結合律,故可以用類似矩陣快速冪的方法剛好做log2k次運算。

最短路總結

寫個部落格記錄一下最短路的幾種演算法,盡量做最正確的解答,減少大家的疑惑,網上有好多講的都抄來抄去,還有好多講的都是錯誤的。熟悉的最短路演算法就幾種 bellman ford,dijkstra,spfa,floyd,下面針對這幾個演算法具體解析一下。首先說明一點,就是關於負環的問題。bellman ...

最短路總結

穿越空間的限制,走最短的路找到你 u v之間的最短路滿足以下限制 對任意k g v,e 有 dist u,v dis u,k dis k,j 關鍵操作 鬆弛 void relax int i,int j,int k floyd void floyd 複雜度o v 3 可處理負環 拓展把所有邊存成負的...

最短路總結

首先是dij演算法,這是我第乙個掌握的最短路演算法!再來是bellman ford演算法,這個演算法比較容易理解,而且考慮到了負環的存在。記住,它對圖中的邊進行了 v 1次操作!首先,對d進行初始化 還有乙個spfa演算法 摘錄於學長空間 設立乙個先進先出的佇列用來儲存待優化的結點,優化時每次取出隊...