代码随想录算法训练营DAY66|Bellman_ford 队列优化算法、Bellman_ford之判断负权回路、Bellman_ford之单源有限最短路

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.城市间货物运输I95.城市间货物运输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个节点,对松弛次数是有限制的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值