dijkstra(迪杰斯特拉)python

 学习笔记仅供参考......(希望对各位有帮助)

简单回顾一下

这里我就直接上代码,先过一遍代码

import heapq

MAX = float('inf')


def dijkstra(graph_matrix, start):
    # 图的顶点数
    num_vertices = len(graph_matrix)

    # 初始化距离列表,用于记录每个顶点到起始顶点的距离
    distances = [float('infinity')] * num_vertices
    #最开始自己和自己的距离当然为0啦
    distances[start] = 0

    # 使用优先队列(堆)来选择距离最短的顶点
    pq = [(0, start)]

    while pq:
        # 从堆中取出距离最短的顶点(用的是优先队列性质)
        current_distance, current_vertex = heapq.heappop(pq)

        # 如果当前距离大于当前顶点到起始顶点的距离,则跳过
        if current_distance > distances[current_vertex]:
            continue

        # 遍历当前顶点的相邻顶点
        for neighbor in range(num_vertices):
            # 如果有连接到相邻顶点的边,并且通过当前顶点到达相邻顶点的距离更短,则更新距离
            if graph_matrix[current_vertex][neighbor] != 0:
                distance = current_distance + graph_matrix[current_vertex][neighbor]
                if distance < distances[neighbor]:
                    distances[neighbor] = distance
                    heapq.heappush(pq, (distance, neighbor))

    return distances


# 示例二维列表表示的图
graph_matrix = [

    [0, 10, MAX, 4, MAX, MAX],
    [10, 0, 8, 2, 6, MAX],
    [MAX, 8, 10, 15, 1, 5],
    [4, 2, 15, 0, 6, MAX],
    [MAX, 6, 1, 6, 0, 12],
    [MAX, MAX, 5, MAX, 12, 0]
]

start_vertex = 0  # 从顶点0开始
distances = dijkstra(graph_matrix, start_vertex)
print("从顶点 {} 到其他顶点的最短距离:".format(start_vertex))
for vertex, distance in enumerate(distances):
    print("到顶点 {} 的最短距离为 {}".format(vertex, distance))
# [0, 6, 11, 4, 10, 16]

简单总结一下,想要完成Dijkstra,那么首先初始化一个邻接表,

(使用字典、元组、二维列表或者列表套以上任何一种都是ok的,这不影响我们思路进行下去....废话)

!!!注意(邻接表是沿对角线对称的)

第二步构造函数

这里呢我们首先要记住我们要什么参数

1、表    2、起始点位置   3、结束点位置

接着记住函数里面初始化

1、初始化距离列表,用于记录每个顶点到起始顶点的距离

2、把堆初始化好这里   "0" 这个位置的含义是当前位置和起始位置的距离,"start"这个位置的含义是就是指当前所在的位置,所以初始化肯定是“0”,开始即是起始点,所以距离为零。

第三步,利用优先队列的特性整他

进入循环

从堆中取出距离最短的顶点,如果当前位置距离起始点距离  比  已经存在distances的最小距离大则下一位谢谢

然后经过一系列筛选后ok,在咱的邻接表中取值更新最终拿到结果(这一行有点懵没关系,看下面的代码注释)

这里的代码我没考虑有多条最短路径所以学习使用请注意

ok上题目,

PAT-天梯赛题目

L2-001 紧急救援

分数 25

作者 陈越

单位 浙江大学

作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。

输入格式:

输入第一行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0 ~ (N−1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。

第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。

输出格式:

第一行输出最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出结尾不能有多余空格。

输入样例:

4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2

输出样例:

2 60
0 1 3

代码长度限制

16 KB

时间限制

200 ms

内存限制

64 MB

代码一:

import heapq


def dijkstra(graph, start, end, num_city):
    # 初始化距离列表(表示的是当前序列号城市到源点城市的距离)
    distances = [float('inf')] * num_city
    distances[start] = 0
    num = [0] * n  # 存储起始点到各个城市的最短路径数量,默认为0
    num[start] = 1  # 起始点到自身的最短路径数量为1

    # 初始化路径列表
    # paths = [[] for _ in range(num_city)]
    # paths[start] = [start]
    # path_end = []
    pre = [-1] * n  # 存储各个城市的前驱城市,默认为-1

    # 初始化救援队数量列表
    rescue = [0] * num_city
    rescue[start] = teams[start]

    # 使用优先队列选择距离最短的点
    pq = [(0, start)]
    while pq:
        # current_distance是指目前城市到起始点的距离
        current_distance, current_city = heapq.heappop(pq)

        # 如果当前城市已经被访问过,则跳过(如果当前距离大于当前顶点到起始顶点的距离,则跳过)
        if current_distance > distances[current_city] or current_city == end:
            continue

        # 遍历当前城市的相邻城市
        for neighbor, distance in graph[current_city]:
            # 如果通过当前城市到达相邻城市的距离更短,则更新距离和路径
            # distance到相邻城市需要的距离
            new_distance = current_distance + distance

            # 如果有连接到相邻顶点的边,并且通过当前顶点到达相邻顶点的距离更短,则更新距离
            if new_distance < distances[neighbor]:
                distances[neighbor] = new_distance  # 更新路径列表
                pre[neighbor] = current_city  # 更新前驱城市
                rescue[neighbor] = rescue[current_city] + teams[neighbor]
                num[neighbor] = num[current_city]  # 更新最短路径数量
                heapq.heappush(pq, (new_distance, neighbor))

            elif new_distance == distances[neighbor]:
                # path_end.append(paths[current_city] + [neighbor])
                num[neighbor] += num[current_city]  # 更新最短路径数量

                if rescue[neighbor] < rescue[current_city] + teams[neighbor]:
                    # paths[neighbor] = paths[current_city] + [neighbor]
                    pre[neighbor] = current_city
                    rescue[neighbor] = rescue[current_city] + teams[neighbor]

    # path_end.append(paths[end])
    return pre, num[d], max(rescue)


# N(2≤N≤500)是城市的个数,顺便假设城市的编号为0 ~ (N−1);
# M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。
n, m, s, d = map(int, input().split())
teams = list(map(int, input().split()))
# 初始化邻接矩阵
graph_matrix = [[] for _ in range(n)]

for _ in range(m):
    city1, city2, length = map(int, input().split())
    graph_matrix[city1].append((city2, length))
    graph_matrix[city2].append((city1, length))

# [
#    [(1, 1), (3, 3), (2, 2)], 
#    [(0, 1), (3, 2)],
#    [(0, 2), (3, 2)], 
#    [(1, 2), (0, 3), (2, 2)]
# ]

pre, l, max_nums = dijkstra(graph_matrix, s, d, n)

print(l, max_nums)
path = []
while d != -1:
    path.append(d)
    d = pre[d]

print(*path[::-1])

代码二

import heapq


def dijkstra(start, end, gragh, city_num):
    distances = [float('inf')] * n
    distances[start] = 0
    # 存储各个城市的前驱城市
    pre = [-1] * n

    # 最短路径条数初始化
    num = [0] * n
    num[start] = 1  # 至少一条最短路径

    # 存储起始点到各个城市经过的救援队数量,默认为0
    # 起始点到自身的救援队数量为自身的救援队数量
    rescue = [0] * n
    rescue[start] = teams[start]  # 注意不要搞错了,是起始点不是0点

    # 初始化堆
    pq = [(0, start)]

    while pq:
        current_distances, current_city = heapq.heappop(pq)

        # 如果当前城市距离起始点距离大于已经存在distances的最小距离大则跳过(如果访问过就跳)
        if current_distances > distances[current_city]:
            continue

        for neighbor in range(city_num):
            if gragh[current_city][neighbor] != float('inf') and gragh[current_city][neighbor] != 0:
                new_distance = current_distances + gragh[current_city][neighbor]
                if new_distance < distances[neighbor]:
                    distances[neighbor] = new_distance
                    num[neighbor] = num[current_city]
                    rescue[neighbor] = rescue[current_city] + teams[neighbor]
                    pre[neighbor] = current_city
                    heapq.heappush(pq, (new_distance, neighbor))

                elif new_distance == distances[neighbor]:
                    num[neighbor] += num[current_city]
                    if rescue[neighbor] < rescue[current_city] + teams[neighbor]:
                        rescue[neighbor] = rescue[current_city] + teams[neighbor]
                        pre[neighbor] = current_city
    return rescue[end], num[end], pre


# 输入第一行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数
# M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。
n, m, s, d = map(int, input().split())
teams = list(map(int, input().split()))
gragh_matrix = [[0 if i == j else float('inf') for i in range(n)] for j in range(n)]  # 22
for i in range(m):
    a, b, c = map(int, input().split())
    gragh_matrix[a][b] = c
    gragh_matrix[b][a] = c  # 别忘了!!!这是对称的
print(gragh_matrix)
# [
#   [0, 1, 2, 3], 
#   [1, 0, inf, 2], 
#   [2, inf, 0, 2], 
#   [3, 2, 2, 0]
#   ]

max_num, max_l, pre = dijkstra(s, d, gragh_matrix, n)
print(max_l, max_num)
path = []
while d != -1:
    path.append(d)
    d = pre[d]
print(*path[::-1])

思路就是这样不过这题目嘛,还是超时

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值