【蓝桥杯 每天一道算法题】最短路

题目描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

如下图所示,G 是一个无向图,其中蓝色边的长度是 1、橘色边的长度是 2、绿色边的长度是 3。

则从 A 到 S 的最短距离是多少?

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

 答案

# 题目链接: https://www.lanqiao.cn/problems/609/learning/
import heapq
from collections import defaultdict

r_list = [
    ["A", "E", 1],
    ["A", "B", 2],
    ["A", "C", 1],
    ["A", "D", 1],
    ["A", "E", 1],
    ["B", "G", 1],
    ["B", "J", 2],
    ["C", "D", 3],
    ["C", "G", 3],
    ["C", "F", 3],
    ["D", "G", 2],
    ["D", "H", 1],
    ["D", "I", 2],
    ["E", "H", 1],
    ["E", "I", 3],
    ["F", "J", 1],
    ["F", "G", 1],
    ["G", "K", 2],
    ["G", "I", 3],
    ["H", "L", 2],
    ["H", "I", 1],
    ["I", "M", 3],
    ["J", "S", 2],
    ["K", "N", 1],
    ["K", "L", 3],
    ["L", "R", 1],
    ["L", "M", 1],
    ["M", "N", 2],
    ["M", "Q", 1],
    ["M", "S", 1],
    ["N", "P", 1],
    ["Q", "O", 1],
    ["O", "R", 3],
    ["P", "O", 1],
    ["R", "S", 1],
]
n = 19
m = len(r_list)

# 参考链接:https://oi-wiki.org/graph/shortest-path/
# 方法1:Floyd 算法
# 时间复杂度是 O(n^3),空间复杂度是 O(n^2)。
f = [[float('inf')] * (n + 1) for _ in range(n + 1)]
# 如果 x 和 y相等,则距离为0
for x in range(1, n + 1):
    for y in range(1, n + 1):
        if x == y:
            f[x][y] = 0
# 如果 x 和 y之间有边相连,则距离为边权
for i in range(m):
    x, y, dis = r_list[i]
    x = ord(x) - ord('A') + 1
    y = ord(y) - ord('A') + 1
    f[x][y] = dis
# 迭代
for k in range(1, n + 1):
    for x in range(1, n + 1):
        for y in range(1, n + 1):
            f[x][y] = min(f[x][y], f[x][k] + f[k][y])
print(f[1][ord('S') - ord('A') + 1])

# 方法2:Dijkstra 算法
# 暴力解法 O(n^2)
# 邻接表存储图
e = [[] for _ in range(1 + n)]
for i in range(m):
    x, y, dis = r_list[i]
    x = ord(x) - ord('A') + 1
    y = ord(y) - ord('A') + 1
    e[x].append((y, dis))
    e[y].append((x, dis))
dis = [float('inf')] * (n + 1)
vis = [False for _ in range(n + 1)]


def dijkstra(n, s):
    dis[s] = 0
    for _ in range(1, n + 1):
        u = 1
        mind = float('inf')
        for j in range(1, n + 1):
            if vis[j] is False and dis[j] < mind:
                u = j
                mind = dis[j]
        vis[u] = True
        for v, w in e[u]:
            if dis[v] > dis[u] + w:
                dis[v] = dis[u] + w


dijkstra(n, 1)
print(dis[ord('S') - ord('A') + 1])

# 优先队列
e = [[] for _ in range(n)]
for i in range(m):
    x, y, dis = r_list[i]
    x = ord(x) - ord('A')
    y = ord(y) - ord('A')
    e[x].append((y, dis))
    e[y].append((x, dis))


def dijkstra(e, s):
    '''
  输入:
  e:邻接表
  s:起点
  返回:
  dis:从s到每个顶点的最短路长度
  '''
    dis = defaultdict(lambda: float("inf"))
    dis[s] = 0
    q = [(0, s)]
    vis = set()
    while q:
        _, u = heapq.heappop(q)
        if u in vis:
            continue
        vis.add(u)
        for v, w in e[u]:
            if dis[v] > dis[u] + w:
                dis[v] = dis[u] + w
                heapq.heappush(q, (dis[v], v))
    return dis


ans = dijkstra(e, 0)
print(ans[ord('S') - ord('A')])

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值