三種演算法
floyd
複雜度 :o(n^3)
應用場景:多源最短路,非負邊
鄰接矩陣存圖
最短路
#
include
#include
#include
using
namespace std;
const
int inf =
0x3f3f3f3f
;int n,m;
const
int max_n =
105;
int d[max_n]
[max_n]
;int
main()
for(
int k =
1;k <= n;k++)}
}printf
("%d\n"
,d[1
][n]);
}return0;
}
dijkstra:
複雜度o(n^2),優先佇列優化後o((n+m)logn)
應用場景:無負邊
鏈式前向星存圖
til the cows come home
#
include
#include
#include
#define
min(x,y) x#define
ppair<
int,
int>
using
namespace std;
const
int inf =
0x3f3f3f3f
;int n,m;
int tot =0;
const
int max_n =
1e3+5;
const
int max_m =
2e3+10;
int d[max_n]
;int edge[max_m<<1]
;int ver[max_m<<1]
;int next[max_m<<1]
;int head[max_m<<1]
;void
add(
int x,
int y,
int z)
void
init()
memset
(d,0x3f
,sizeof
(d));}
intmain()
priority_queue< p > q;
//優先佇列以pair第一維大到小排序,由最短路(最小值),所以放入(-d[i])
d[n]=0
; q.
push(p
(0,n))
;while
(q.size()
)}}printf
("%d"
,d[1])
;return0;
}
其中(-p.first > d[u])有另一種方式
用vis陣列
if
(vis[u]
)continue
;else
2021.7.13更新
今天學了bellman-ford演算法, 原因在於這道題
currency exchange
題意是:有n種貨幣,給你一些某種貨幣, 你要不斷的換錢,使自己的錢增加。而換幣會有匯率和服務費。容易發現, 如果存在乙個環, 通過不斷地換幣回到同一種貨幣, 若錢的數量增多, 則存在bug可以無限刷錢,輸出yes, 不然輸出no
知識點:bellman-ford演算法和最長路
先講bellman-ford(沒有佇列優化)
**如下
void
bellman()
if(!flag)
break;}
}
性質1:不存在負環的情況下, 有效更新最多進行n - 1次,計算的d就一定是最短路
解釋:參考dijkstra演算法, 邊權為正數時,每次至少有乙個點更新到最小值。
不同的是, bellman在有負邊的情況下仍能正常工作, 只要不存在負環, 原因是是, 最短路一定是簡單路徑, 每次迴圈時, 能擴充出乙個正確的點。
推論1:以最短路為例, 若第n次仍有邊滿足d[u] + w < d[v], 則存在負環, 最短路不可求
可以用佇列優化:
void
spfa()
}}}
佇列優化能用的原因仍可以用簡單路徑解釋, 最短路上的第二個點離起點距離為1, 將所有距離為1的點更新完後, 再更新距離為2的點
知識點2:最長路
這個其實不難, 將不等號方向變相即可輕鬆實現。此時dijkstra不能判斷正邊, bellman可以判斷有無正環
學習筆記最短路徑
n個城市,標號從0到n 1,m條道路,第k條道路 k從0開始 的長度為2 k,求編號為0的城市到其他城市的最短距離 第一行兩個正整數n 2 n 100 m m 500 表示有n個城市,m條道路 接下來m行兩個整數,表示相連的兩個城市的編號n 1行,表示0號城市到其他城市的最短路,如果無法到達,輸出 ...
最短路 Dijkstra學習筆記
最近蒟蒻的自己重新學習了一遍最短路,也算有些體會,記錄下來。首先引入問題 在一張圖中,從某一頂點出發,沿圖的邊到達定乙個頂點所經過的路徑中,各邊權值和最小的一條路徑。解決該問題的演算法有 dijkstra演算法,bellman ford 演算法,floyd 演算法和spfa 演算法介紹 dijkst...
Dijkstra學習筆記 單源最短路
dijkstra是通過貪心來進行實現的。所以不能判定有負邊的圖。看一下這張圖,我們從1 11號點開始遍歷,且令dis ti dist i disti 為第i ii個點到1 11好點的最短路徑。首先我們把已知最短路的點設為長方形,未知的設為圓形即可,那麼一號點就是已知的,及dis t1 0 dist ...