蓝桥杯算法题——最短路(Python SPFA方法)

蓝桥杯算法题——最短路(Python SPFA方法)

  • 题目重现
    • 问题描述
    • 输入格式
    • 输出格式
    • 输入样例
    • 输出样例
    • 数据规模与约定
  • 解题思路
    • 可能的坑
  • 代码

题目重现

蓝桥杯算法题 ALGO-5 最短路

原题链接:link.

问题描述

给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环)。请你计算从1号点到其他点的最短路(顶点从1到n编号)。

输入格式

第一行两个整数n, m。

接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边。

输出格式

共n-1行,第i行表示1号点到i+1号点的最短路。

输入样例

3 3
1 2 -1
2 3 -1
3 1 2

输出样例

-1
-2

数据规模与约定

对于10%的数据,n = 2,m = 2。

对于30%的数据,n <= 5,m <= 10。

对于100%的数据,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保证从任意顶点都能到达其他所有顶点。

解题思路

树形动态规划算法题,最短路径问题。

由于有负权值,不能够使用Dijkstra算法。

Floyd算法、BF(Bellman-Ford)算法由于时间复杂度较大,存在超时可能。

这里考虑SPFA算法,通过松弛边的方法,维护可能的结点FIFO队列line与各点到结点1的距离列表dis。

(注:SPFA 最坏情况下复杂度和朴素 Bellman-Ford 相同)

可能的坑

这里存储边的数据结构的选择会影响后面SPFA算法的运行时间。

经过尝试,字典的列表形式优于二维数组的形式,能够提高访问效率。

# 字典的列表:
[{
     },{
     "j":weight},{
     },{
     },...{
     }]
# 列表中第i个字典中键j及其值weight代表结点i与结点j之间的权重为weight

# 二维数组
[ [0,0,0, ... , 0] ,
  [0,0,0, ... , 0] ,
  ... ,
  [0,0,0, ... , 0] ]

代码

# SPFA
# 蓝桥杯 最短路
# Author:韩仙男   2021-01-28

n,m = map(int,input().split())
dis = [float("inf") for _ in range(n)]
dis[0] = 0

edges = [ dict() for _ in  range(n)]

for _ in  range(m):
    f,t,weight = map(int,input().split())
    edges[f-1][t] = weight

line = [1]

while line != []:
    current_point = line[0]
    for t_point,weight in edges[current_point-1].items():
        if dis[t_point-1] > dis[current_point-1] + weight:
            dis[t_point-1] = dis[current_point-1] + weight
            if t_point not in line:
                line.append(t_point)
    line.remove(current_point)

for _ in range(1,n):
    print(dis[_])

你可能感兴趣的:(Python刷题,算法,python,数据结构,leetcode,动态规划)