Bellman-Ford算法
伪代码:
for n次
//backup[]备份
for 所有边 a , b , w
dist[b] = min(dist[b], dist[a] +w);//松弛操作
//dist[b] = min(dist[b], backup[a] +w);
if(dist[n]>0x3f3f3f3f/2) return -1;
解析:
- 备份:
只用上次更新结果,防止发生串联
第k次 表示不超过k条边,第n次 更新 ,则存在负环 - 松弛操作:
dist[b] = min(dist[b], dist[a] +w); - 三角不等式:
dist[b] <= dist[a] + w;
遍历结束后,所有边满足三角不等式 - 技巧:
防止负权边更新的最短路距离小于正无穷:if(dist[n]>0x3f3f3f3f/2) return -1;
存储:
struct{
int a , b , w;
}edge[M];
时间复杂度:O(nm)
注意:
如果有负权回路,最短路不一定 存在
可以用来找负环,但一般不用
SPFA算法
宽搜优化Bellman-Ford:
伪代码:
queue <- 1
while queue 不空
t <- q.front; // 取出队头
q.pop();
queue <- b //更新t的所有出边
与堆优化版Dijkstra算法类似
都可先用SPFA做,卡再换
网格图一般容易卡SPFA
求负环
存储及更新:
dist[x] 最短距离 dist[x] = dist[t] + w[i];
cnt[x] 边数 cnt[x] = cnt[t] + 1;
cnt[x] >= n 则有负环
初始时将所有点都放入st[i]
for(int i=1;i<=n;i++){
st[i] = true;
q.push(i);
}
1.14小结
- 《算法基础课》
- 刷题
牛客*3 - cf Round 102 (Div.2)
A - √
B - √