📜  门| GATE-CS-2016(套装2)|问题 9(1)

📅  最后修改于: 2023-12-03 15:42:18.809000             🧑  作者: Mango

门 | GATE-CS-2016(套装2)|问题 9

本道问题是一道关于图论的问题。题目所给图是一个有向图,每一个节点表示一个城市,每一条边表示从一个城市到另一个城市的道路。每一个城市都会有一个数值,这个数值表示在这个城市需要花费的费用。现在,你需要从起点S出发,到达终点T,并且尽可能地节省费用。请你计算从S到T的最小花费。

本题可以使用 Dijkstra 算法来解决,下面是代码片段:

import heapq

def dijkstra(edges, f, t):
    g = defaultdict(list)
    for l,r,c in edges:
        g[l].append((c,r))

    q, seen, mins = [(0,f,())], set(), {f: 0}
    while q:
        (cost,v1,path) = heapq.heappop(q)
        if v1 not in seen:
            seen.add(v1)
            path = (v1, path)
            if v1 == t: return (cost, path)

            for c, v2 in g.get(v1, ()):
                if v2 in seen: continue
                prev = mins.get(v2, None)
                next = cost + c
                if prev is None or next < prev:
                    mins[v2] = next
                    heapq.heappush(q, (next, v2, path))

    return float("inf")

### 用法示例
graph = [(0,1,1), (1,2,1), (2,3,1), (0,3,10)]
print(dijkstra(graph, 0, 3)) # (3, (3, (2, (1, (0, ())))))

这里我们通过构建一个邻接表,将图存储在 defaultdict 中。首先,将起点S和当前花费0加入到一个优先队列中,然后重复从队列中取出一个元组 (当前花费、当前节点、路径)。如果当前节点在 seen 集合中不存在,则将当前节点加入 seen 集合中,并将其添加到路径中。如果当前节点是终点T,则返回已经确定的最小花费和路径。如果当前节点不是终点,则我们枚举当前节点的所有邻接边,并通过一个小根堆(使用 heapq 模块)来找到要探索的下一个节点。如果新的路径长度比已知的路径长度更短,则我们记录最短路径长度并添加一个节点到优先队列中。我们一直执行此过程,直到找到终点T或遍历完整个图。最后,我们返回最短路径和所需的花费。