Bellman_ford 队列优化算法(又名SPFA)
from collections import deque, defaultdict
def SPFA(graph,n):
min_dist = [float('inf')]*n
min_dist[0]=0
que = deque([0])
while que:
cur = que.popleft()
for edge in graph[cur]:
to_ = edge[0]
val = edge[1]
if min_dist[cur]!=float('inf') and min_dist[to_]>min_dist[cur]+val:
min_dist[to_]=min_dist[cur]+val
que.append(to_)
if min_dist[-1]==float('inf'):
print('unconnected')
else:
print(min_dist[-1])
if __name__=='__main__':
n,m=map(int, input().split())
graph = defaultdict(list)
for _ in range(m):
s,t,v = map(int, input().split())
graph[s-1].append([t-1,v])
SPFA(graph,n)
Bellman_ford之判断负权回路
- 超时版
def bellman_ford(graph, n):
mindist = [float('inf')]*n
mindist[0]=0
for i in range(n):
update = False
for edge in graph:
from_ = edge[0]
to_ = edge[1]
val = edge[2]
if i<n-1:
if mindist[from_]!=float('inf') and mindist[to_]>mindist[from_]+val:
mindist[to_]=mindist[from_]+val
update = True
elif mindist[from_]!=float('inf') and mindist[to_]>mindist[from_]+val:
print('circle')
return
if not update:
break
if mindist[-1]!=float('inf'):
print(mindist[-1])
else:
print('unconnected')
if __name__=='__main__':
n,m = map(int, input().split())
graph = []
for _ in range(m):
s,t,v = map(int, input().split())
graph.append([s-1,t-1,v])
bellman_ford(graph,n)
- SPFA
from collections import defaultdict, deque
def SPFA(graph, n):
mindist = [float('inf')]*n
mindist[0]=0
que = deque([0])
count = [0]*n
count[0]=1
while que:
cur = que.popleft()
for edge in graph[cur]:
to_ = edge[0]
val = edge[1]
if mindist[cur]!=float('inf') and mindist[to_]>mindist[cur]+val:
mindist[to_]=mindist[cur]+val
que.append(to_)
count[to_]+=1
if count[to_]==n:
print('circle')
return
if mindist[-1]!=float('inf'):
print(mindist[-1])
else:
print('unconnected')
if __name__=='__main__':
n,m = map(int, input().split())
graph = defaultdict(list)
for _ in range(m):
s,t,v = map(int, input().split())
graph[s-1].append([t-1,v])
SPFA(graph,n)
Bellman_ford之单源有限最短路
def bellman_ford(graph, n, src, dst, k):
mindist = [float('inf')]*n
mindist[src]=0
for i in range(k+1):
mindist_copy = mindist.copy()
update = False
for edge in graph:
from_,to_,val = edge
if mindist_copy[from_]!=float('inf') and mindist[to_]>mindist_copy[from_]+val:
mindist[to_] = mindist_copy[from_]+val
update = True
if not update:
break
if mindist[dst]==float('inf'):
print('unreachable')
else:
print(mindist[dst])
if __name__ =='__main__':
n,m = map(int, input().split())
graph = []
for _ in range(m):
s,t,v = map(int, input().split())
graph.append([s-1,t-1,v])
src,dst,k = map(int, input().split())
bellman_ford(graph, n, src-1, dst-1, k)
- 需要使用mindist_copy的情况
那么前面讲解过的 94.城市间货物运输I 和 95.城市间货物运输II 也是bellman_ford经典算法,也没使用 minDist_copy,怎么就没问题呢?-
94.城市间货物运输I, 是没有 负权回路的,那么 多松弛多少次,对结果都没有影响。
求 节点1 到 节点n 的最短路径,松弛n-1 次就够了,松弛 大于 n-1次,结果也不会变。
那么在对所有边进行第一次松弛的时候,如果基于 本次计算的 minDist 来计算 minDist (相当于多做松弛了),也是对最终结果没影响。 -
95.城市间货物运输II 是判断是否有 负权回路,一旦有负权回路, 对所有边松弛 n-1 次以后,在做松弛 minDist 数值一定会变,根据这一点来判断是否有负权回路。
所以,95.城市间货物运输II 只需要判断minDist数值变化了就行,而 minDist 的数值对不对,并不是我们关心的。 -
那么本题 为什么计算minDist 一定要基于上次 的 minDist 数值。
其关键在于本题的两个因素:- 本题可以有负权回路,说明只要多做松弛,结果是会变的。
- 本题要求最多经过k个节点,对松弛次数是有限制的。
-

474

被折叠的 条评论
为什么被折叠?



