算法-Bellman-Ford
前置知识
思路
Bellman-Ford 是一种单源最短路算法,可以得到一个不含有负环的图上由一个点出发的最短路(即单源最短路)。
我们记录
d
d
d 数组为距离数组。
每次我们遍历每一条边
(
u
,
v
,
w
)
(u,v,w)
(u,v,w),若
d
v
>
d
u
+
w
d_v>d_u+w
dv>du+w 则
d
v
←
d
u
+
w
d_v\gets d_u+w
dv←du+w 称为一次松弛。
我们一共遍历
∣
V
∣
−
1
|V|-1
∣V∣−1 轮,一共应产生
∣
V
∣
−
1
|V|-1
∣V∣−1 次松弛,此时
d
d
d 即为答案。
我们不妨来举一个例子。
读者不妨在这里手动模拟一下,我就放个答案了啊。
d
2
d
3
d
4
d
5
3
4
1
3
\begin{matrix}d_2&d_3&d_4&d_5\\3&4&1&3\end{matrix}
d23d34d41d53
我们发现,Bellman-Ford 的操作其实类似于DP。
基于这样的原理,Bellman-Ford 可以用来判断负环,若松弛超过 ∣ V ∣ − 1 |V|-1 ∣V∣−1 次即存在负环。
算法参数
- 平均时间复杂度: O ( ∣ V ∣ ∣ E ∣ ) O(|V||E|) O(∣V∣∣E∣)
- 最坏时间复杂度: O ( ∣ V ∣ ∣ E ∣ ) O(|V||E|) O(∣V∣∣E∣)
- 空间复杂度: O ( ∣ V ∣ + ∣ E ∣ ) O(|V|+|E|) O(∣V∣+∣E∣)
实现代码
void bellman_ford(int s){
memset(d,INF,sizeof(d));
d[s]=0;
for (int i=1;i<=n-1;i++)
for (int u=1;u<=n;u++)
for (edge e:G[u])
if (d[e.v]>d[u]+e.w)
d[e.v]=d[u]+e.w;
}