挣扎数学建模:各种算法汇总(4)图论dijistra算法

Di jkstra算法能求-一个顶点到另一顶点最短路径。它是由Di jkstra于1959年提出的。实际它能出始点到其它所有顶点的最短路径。Dijkstra算法是- -种标号法:给赋权图的每一- 个顶点记一个数,称为顶点的标号(临时标号,称T标号,或者固定标号,称为P标号)。T标号表示从始顶点到该标点的最短路长的上界; P标号则是从始顶点到该顶点的最短路长。

将给定的路径图转换成mtx_graph的矩阵,aij表示第i个地点到第j个地点的距离。自己和自己的距离用0表示,无法直接连通的用inf表示(无穷大)。后面只需更换不同的矩阵即可,十分适用

# 以下代码经测试 可行
from collections import defaultdict
from heapq import *

inf = 99999  # 不连通值
mtx_graph = [[0, 2, 4, inf, inf, inf, inf],
             [inf, 0, inf, 3, 3, 1, inf],
             [inf, inf, 0, 2, 3, 1, inf],
             [inf, inf, inf, 0, inf, inf, 1],
             [inf, inf, inf, inf, 0, inf, 3],
             [inf, inf, inf, inf, inf, 0, 4],
             [inf, inf, inf, inf, inf, inf, 0]]
m_n = len(mtx_graph)  # 带权连接矩阵的阶数 9
edges = []  # 保存连通的两个点之间的距离(点A、点B、距离)
for i in range(m_n):
    for j in range(m_n):
        if i != j and mtx_graph[i][j] != inf:
            edges.append((i, j, mtx_graph[i][j]))
# print(edges)

def dijkstra(edges, from_node, to_node):
    go_path = []
    to_node = to_node - 1
    g = defaultdict(list)
    for l, r, c in edges:
        # l:点A r:点B c:距离
        # 字典: 点A -> (距离,点B)
        g[l].append((c, r))
    q, seen = [(0, from_node - 1, ())], set()
    while q:
        (cost, v1, path) = heappop(q)  # 堆弹出当前路径最小成本
        if v1 not in seen:
            seen.add(v1)
            path = (v1, path)
            if v1 == to_node:
                break
            for c, v2 in g.get(v1, ()):
                if v2 not in seen:
                    heappush(q, (cost + c, v2, path))

    if v1 != to_node:  # 无法到达
        return float('inf'), []
    if len(path) > 0:
        left = path[0]
        go_path.append(left)
        right = path[1]
        while len(right) > 0:
            left = right[0]
            go_path.append(left)
            right = right[1]

        go_path.reverse()  # 逆序变换
        for i in range(len(go_path)):  # 标号加1
            go_path[i] = go_path[i] + 1
    return cost, go_path


leght, path = dijkstra(edges, 1, 7)
print('最短距离为:' + str(leght))
print('前进路径为:' + str(path))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值