代码随想录算法训练营第五十九天|94. 城市间货物运输 I 95. 城市间货物运输 II 96. 城市间货物运输 III

94. 城市间货物运输 I

94. 城市间货物运输 I

代码随想录

思路:今天的题目都是Bellman_ford 算法,思路就是要根据点的数量n来进行n次全部“松弛”(代表最多走n-1条边到达终点),所谓松弛就是在对每一个条边进行计算,判断能否出现更短的路径,主要是为了解决可能出现的负权值情况(这道题没有),所以要不断的重复遍历。而因为每一次遍历的所有edges都是一样的,所以如果一次遍历后没有修改任何值,那以后也不会修改了,可以直接break

n,m=map(int,input().strip().split())
edges=[]
for _ in range(m):
    s,t,v=map(int,input().strip().split())
    edges.append((s,t,v))
minDist=[float('inf')]*(n+1)
minDist[1]=0
for i in range(1,n):
    update=False
    for start,end,val in edges:
        if minDist[start]!=float('inf') and minDist[start]+val<minDist[end]:
            minDist[end]=minDist[start]+val
            update=True
    if update==False:
        break
if minDist[-1]==float('inf'):
    print("unconnected")
else:
    print(minDist[-1])

之后还有一个队列优化的方法,因为只有被初始化(即赋值不是inf)的才会考虑,所以我们只需要把每一次加入的新节点加入队列就可以了,而当这个节点被使用过后要把visit数组改成false(因为可能需要重复经过这个点。在邻接表的初始化的时候要注意[[] for _ in range(n+1)]而不是[[]*(n+1)]因为这样会导致实际上还是一个[]

from collections import deque
n,m=map(int,input().split())
graph=[[] for _ in range(n+1)]
for _ in range(m):
    s,t,v=map(int,input().split())
    graph[s].append((t,v))
minDist=[float('inf')]*(n+1)
minDist[1]=0
visit=[False]*(n+1)
visit[1]=True
que=deque([1])
while que:
    cur=que.popleft()
    visit[cur]=False
    for dest,val in graph[cur]:
        if minDist[cur]!=float('inf') and minDist[cur]+val<minDist[dest]:
            minDist[dest]=minDist[cur]+val
            if visit[dest]==False:
                visit[dest]=True
                que.append(dest)
if minDist[-1]==float('inf'):
    print("unconnected")
else:
    print(minDist[-1])

95. 城市间货物运输 II

95. 城市间货物运输 II

代码随想录

思路:这道题就是会有负权值回路,导致无限循环的话,值会越来越小,为了避免这种情况,所以在最后新加一次计算,如果有改变,那说明存在负回路

n,m=map(int,input().strip().split())
edges=[]
for _ in range(m):
    s,t,v=map(int,input().strip().split())
    edges.append((s,t,v))
minDist=[float('inf')]*(n+1)
minDist[1]=0
flag=False
for i in range(1,n+1):
    for start,end,val in edges:
        if i<n:
            if minDist[start]!=float('inf') and minDist[start]+val<minDist[end]:
                minDist[end]=minDist[start]+val
        if i==n:
            if minDist[start]!=float('inf') and minDist[start]+val<minDist[end]:
                flag=True
if flag==True:
    print("circle")
elif minDist[-1]==float('inf'):
    print("unconnected")
else:
    print(minDist[-1])

96. 城市间货物运输 III

96. 城市间货物运输 III

代码随想录

思路:这道题的特别是在最多只能经过k个城市(算上起点和终点一共经过k+1条边),看起来只需要循环限制为k+1次,但实际上并不是,因为每一次的遍历可能会使用在这一轮遍历新修改的值,而不是上一轮修改后的值,导致并不是严格的k+1次,因此每一轮我们都要使用一个副本,复制一下开始时的minDist数组

n,m=map(int,input().split())
edges=[]
for _ in range(m):
    s,t,v=map(int,input().split())
    edges.append((s,t,v))
src,dst,k=map(int,input().split())
minDist=[float('inf')]*(n+1)
minDist[src]=0
for _ in range(k+1):
    update=False
    minDist_c=minDist[:]
    for start,end,val in edges:
        if minDist_c[start]!=float('inf') and minDist_c[start]+val<minDist[end]:
            minDist[end]=minDist_c[start]+val
            update=True
    if not update:
        break
if minDist[dst]==float('inf'):
    print("unreachable")
else:
    print(minDist[dst])


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值