Bellman_ford 不同场景的应用。
题目1: Bellman_ford 队列优化算法
对于bellman_ford做了队列优化,也就是这个判断 minDist[from] != Int.max 用队列替换了。 bellman_ford基础版本
func bellmanFordQueue(n: Int, e: Int, grid: [[Int]]) {
var minDist = Array(repeating: Int.max, count: n + 1)
// 此题中元素是否有被加入queue中可以不用统计, 重复加入正权回路 最后没问题。 负权回路本题限制不会出现。
var inqueue = Array(repeating: false, count: n + 1)
var stack = [Int]()
// 邻接表 from: [(to: val)]
var map = [Int: [(Int, Int)]]()
for line in grid {
var list = map[line[0], default: []]
list.append((line[1], line[2]))
map[line[0]] = list
}
print("\(map)")
minDist[1] = 0
inqueue[1] = true
stack = [1]
while !stack.isEmpty {
let from = stack.removeLast()
inqueue[from] = false
for line in map[from] ?? [] {
if minDist[line.0] > minDist[from] + line.1 {
minDist[line.0] = minDist[from] + line.1
if inqueue[line.0] == false {
stack.append(line.0)
inqueue[line.0] = true
}
}
}
}
if minDist[n] == Int.max {
print("unconnected")
} else {
print("\(minDist[n])")
}
}
bellmanFordQueue(n: 6, e: 5, grid: [[5, 6, 1], [4, 5, 1], [3, 4, 1], [2, 3, 1], [1, 2, 1]]) // 5
bellmanFordQueue(n: 6, e: 7, grid: [[5, 6, -2], [1, 2, 1], [5, 3, 1], [2, 5, 2], [2, 4, -3], [4, 6, 4], [1, 3, 5]]) // 1
bellmanFordQueue(n: 4, e: 2, grid: [[1, 2, -1], [3, 4, -1]]) // unconnected
题目2: bellman_ford之判断负权回路
负权回路终于出现了。
负权回路的处理,基于以上两种都可以做判断。
- bellmanFord 算法,如果没有负权回路最多松弛n-1次就不会变化了,所以可以统计如果松弛第n次 还有变化,那么就是有负权回路了。
- bellmanFord 队列优化算法, 每个点最多被连接n-1次, 如果发现某个点被入队n次, 那么就是有负权回路了。
题目3:bellman_ford之单源有限最短路
有限的路径。
其中的重点是 每次要使用上轮计算的结果来做松弛, 而不是在本次的基础上。
这样的话因为有负权回路的存在,每多执行一次, 结果就会有变化。
而前面不用考虑的原因是:
- 判断负权回路 : 都是判断最多执行n-1次就不应该变化了。 中间多执行几次,相当于提前完成了n-1次,那么到实际遍历了n-1次时,如果有负权回路,依旧会变化,如果没负权回路,早就不变化了。 对结果没影响。
- bellman_ford基础版本: 没有负权回路 多执行几次并不会改变结果。
func bellmanFordLimitK(n: Int, e: Int, grid: [[Int]]) {
var minDist = Array(repeating: Int.max, count: n + 1)
let src = grid[grid.count - 1][0]
let dst = grid[grid.count - 1][1]
let k = grid[grid.count - 1][2]
let grid = grid[0..<(grid.count - 1)]
minDist[src] = 0
print("\(grid) - \(src) \(dst) \(k)")
for _ in 0...k {
let minDistCopy = minDist
minDist[0] = 2
for line in grid {
let from = line[0]
let to = line[1]
let val = line[2]
if minDistCopy[from] != Int.max, minDist[to] > minDistCopy[from] + val {
minDist[to] = minDistCopy[from] + val
}
}
}
if minDist[dst] == Int.max {
print("unconnected")
} else {
print("\(minDist[dst])")
}
}
bellmanFordLimitK(n: 6, e: 7, grid: [[1, 2, 1], [2, 4, -3], [2, 5, 2], [1, 3, 5], [3, 5, 1], [4, 6, 4], [5, 6, -2], [2, 6, 1]]) // 0
bellmanFordLimitK(n: 4, e: 4, grid: [[3, 1, -1], [3, 4, 1], [2, 3, 1], [1, 2, -1], [1, 4, 3]]) // 1