代码随想录算法训练营day73 | dijkstra(堆优化版)、Bellman_ford算法

本次题目都来自卡码网

47. 参加科学大会(dijkstra(堆优化版))

从 堆里取堆顶元素(小顶堆中,最小的权值在上面),就可以取到离源点最近的节点了 (未访问过的节点,不会加到堆里进行排序)

使用邻接表进行存储

import heapq


# 定义一个类来表示带权重的边
class Edge:
    def __init__(self, to, val):
        self.to = to  # 邻接顶点
        self.val = val  # 边的权重


if __name__ == '__main__':
    n, m = map(int, input().split())
    grid = [[] for _ in range(n + 1)]

    for _ in range(m):
        origin, destination, val = map(int, input().split())
        grid[origin].append(Edge(destination, val))

    start = 1  # 起点
    end = n  # 终点
    minDist = [float('inf')] * (n + 1)  # 存储从源点到每个节点的最短距离
    visited = [False] * (n + 1)  # 记录顶点是否被访问过
    priority_queue = []  # 优先队列中存放 pair<源点到该节点的权值,节点>
    heapq.heappush(priority_queue, (0, start))  # 初始化队列,源点到源点的距离为0,所以初始为0
    minDist[start] = 0  # 起始点到自身的距离为0
    while priority_queue:
        # 1. 第一步,选源点到哪个节点近且该节点未被访问过 (通过优先级队列来实现)
        cur_dist, cur_node = heapq.heappop(priority_queue)
        # 2. 第二步,该最近节点被标记访问过
        if visited[cur_node]:
            continue
        visited[cur_node] = True
        # 3. 第三步,更新非访问节点到源点的距离(即更新minDist数组)
        for edge in grid[cur_node]:  # 遍历 cur指向的节点,cur指向的节点为 edge
            # cur指向的节点edge.to,这条边的权值为 edge.val
            if (not visited[edge.to]) and cur_dist + edge.val < minDist[edge.to]:
                minDist[edge.to] = cur_dist + edge.val
                heapq.heappush(priority_queue, (minDist[edge.to], edge.to))

    if minDist[end] == float('inf'):
        print(-1)
    else:
        print(minDist[end])

94. 城市间货物运输 I(Bellman_ford算法)

Bellman_ford 是可以计算 负权值的单源最短路算法。其算法核心思路是对 所有边进行 n-1 次 松弛。

对所有边松弛一次,相当于计算 起点到达 与起点一条边相连的节点 的最短距离。

无论图是什么样的,边是什么样的顺序,我们对所有边松弛 n-1 次 就一定能得到 起点到达 终点的最短距离。

下面代码超时

if __name__ == '__main__':
    n, m = map(int, input().split())
    grid = []
    for i in range(m):
        p1, p2, val = map(int, input().split())
        grid.append((p1, p2, val))

    start = 1  # 起点
    end = n  # 终点

    minDist = [float('inf')] * (n + 1)
    minDist[start] = 0

    for _ in range(n - 1):  # 对所有边 松弛 n-1 次
        for side in grid:  # 每一次松弛,都是对所有边进行松弛
            _from = side[0]  # 边的出发点
            to = side[1]  # 边的到达点
            price = side[2]  # 边的权值
            # 松弛操作
            # minDist[from] != INT_MAX 防止从未计算过的节点出发
            if minDist[_from] != float('inf') and minDist[to] > minDist[_from] + price:
                minDist[to] = minDist[_from] + price

    if minDist[end] == float('inf'):
        print("unconnected")  # 不能到达终点
    else:
        print(minDist[end])  # 到达终点最短路径

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值