代码随想录算法训练营第62天 | 最短路径:dijkstra(堆优化版)+ Bellman_ford算法

47.参加科学大会
https://kamacoder.com/problempage.php?pid=1047
dijkstra(堆优化版)精讲
https://www.programmercarl.com/kamacoder/0047.参会dijkstra堆.html#思路
94.城市间货物运输 I
https://kamacoder.com/problempage.php?pid=1152
Bellman_ford 算法精讲
https://www.programmercarl.com/kamacoder/0094.城市间货物运输I.html#思路

dijkstra(堆优化版)精讲

  • 优化部分:

    • 用邻接列表:不需要一个一个遍历;
    • 用优先堆:不需要找最小值;每次pop出来的就是最小值;
    • 只需要更新mindist
    点击查看代码
    import heapq
    def dijkstra(n, m, grid, start, end):
    	mindist = [float("inf")]*(n+1)
    	visited = [False]*(n+1)
    	mindist[start] = 0
    	pq = [(0,start)]
    	##堆优化
    	while pq:
    		curr_val,u = heapq.heappop(pq)
    		if visited[u]:
    			continue
    		for v,weight in grid[u]:
    			##更新堆
    			if not visited[v] and curr_val+weight<mindist[v]:
    				mindist[v] = curr_val+weight
    				heapq.heappush(pq,(mindist[v],v))
    	if mindist[end]==float("inf"):
    		return -1
    	else:
    		return mindist[end]
    def main():
    	n,m = map(int,input().split())
    	grid = [[] for _ in range(n+1)]
    	for i in range(m):
    		s,e,v = map(int,input().split())
    		grid[s].append((e,v))
    	res = dijkstra(n,m,grid,1,n)
    	print(res)
    
    if __name__ == '__main__':
    	main()
    

94. 城市间货物运输 I

某国为促进城市间经济交流,决定对货物运输提供补贴。共有 n 个编号为 1 到 n 的城市,通过道路网络连接,网络中的道路仅允许从某个城市单向通行到另一个城市,不能反向通行。
网络中的道路都有各自的运输成本和政府补贴,道路的权值计算方式为:运输成本 - 政府补贴。权值为正表示扣除了政府补贴后运输货物仍需支付的费用;权值为负则表示政府的补贴超过了支出的运输成本,实际表现为运输过程中还能赚取一定的收益。
请找出从城市 1 到城市 n 的所有可能路径中,综合政府补贴后的最低运输成本。如果最低运输成本是一个负数,它表示在遵循最优路径的情况下,运输过程中反而能够实现盈利。
城市 1 到城市 n 之间可能会出现没有路径的情况,同时保证道路网络中不存在任何负权回路。

Bellman_ford 算法精讲

  • 核心思想:对所有边进行松弛n-1次操作(n为节点数量),从而求得目标最短路。

  • 松弛:当前节点最小值更新:每个入度:

    • if minDist[B]>minDist[A]+value:
      minDist[B] = minDist[A]+value
  • 需要松弛几次才能得到起点到终点的最短距离

    • 我们对所有边松弛 n-1 次 就一定能得到 起点到达 终点的最短距离。
  • 停止:如果本次没有更新;就停止更新

    点击查看代码
    def bellman(n,m,edges,start,end):
    	mindist = [float("inf")]*(n+1)
    	mindist[start] = 0
    	###松弛n-1次
    	for _ in range(n):
    		update = False
    		##松弛每个边上的节点
    		for s,t,v in edges:
    			if mindist[s]!=float("inf") and mindist[t]>mindist[s]+v:
    				mindist[t] = mindist[s]+v
    				update = True
    		if not update:
    			break
    	if mindist[end]==float("inf"):
    		return "unconnected"
    	else:
    		return mindist[end]
    
    def main():
    	n,m = map(int,input().split())
    	edges = []
    	for i in range(m):
    		s,t,v = map(int,input().split())
    		edges.append((s,t,v))
    	res = bellman(n,m,edges,1,n)
    	print(res)
    
    if __name__ == '__main__':
    	main()
    
posted @ 2024-08-07 10:54  哆啦**  阅读(2)  评论(0编辑  收藏  举报