📜  门| GATE CS Mock 2018 |第 55 题(1)

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

门 GATE CS Mock 2018 | 第 55 题

这道题目是 GATE 计算机科学模拟考试的第 55 题。这题主要考察程序员对于图结构的理解和基本算法的实现。

题目描述

给定一个有向图 $G=(V,E)$,其中 $V$ 是一组顶点,$E$ 是一组有向边。图中每个顶点都有一个权重 $w(i)$,且所有权重都是正整数。现在,假设顶点 $s$ 是起始顶点,顶点 $d$ 是目标顶点。你要从顶点 $s$ 出发,遍历图中的所有顶点,然后到达顶点 $d$。

你的目标是:找到一条路径 $P$,使得 $P$ 的所有顶点的权重之和最小。请实现一个算法,以便找到这条最短路径。

输入格式

输入由以下几行构成:

  • 第一行包含两个整数 $n$ 和 $m$,表示顶点数和边数。
  • 接下来 $n$ 行,每行一个正整数 $w_i$,表示顶点 $i$ 的权重。
  • 接下来 $m$ 行,每行三个整数 $u_i, v_i, w_i$,表示边 $(u_i, v_i)$,权重为 $w_i$。
输出格式

输出一个整数,表示顶点 $s$ 到顶点 $d$ 的最短路径权值之和。

示例
输入示例 1
5 7
1
2
3
4
5
1 2 2
1 3 3
2 3 3
2 4 4
3 4 1
3 5 5
4 5 1
输出示例 1
7
解题思路

这道题目考察的算法是 Dijkstra 算法,这是一种经典的求解单源最短路径问题的算法。下面是详细的解题思路:

  1. 首先,我们需要读入输入数据,包括图的顶点数、边数,以及每个顶点的权重值等信息。
  2. 创建一个 Dijkstra 算法需要的数据结构,包括一个每个顶点的到起始点的距离的数组 $dist$,以及一个记录每个点是否已被访问过的数组 $visited$。初始化 $dist$ 数组,把起始点的距离设置为 0,其他点的距离设置为一个非常大的值(如 $10^9$),$visited$ 数组设为全部为 false。
  3. 使用堆优化的 Dijkstra 算法求解最短路径。首先,将起始点 $s$ 加入到一个最小堆 $q$ 中,堆中每个元素的 key 值是顶点 $v$ 的距离 $dist[v]$。然后,从堆中取出 $dist$ 值最小的顶点 $u$,把它加入到 $visited$ 数组中。接着,遍历所有与 $u$ 相邻的节点 $v$,计算 $dist[v]$ 的值。如果 $dist[u] + w(u,v) < dist[v]$,则更新 $dist[v]$ 的值为 $dist[u] + w(u,v)$。如果顶点 $v$ 尚未出现在堆中,就将它加入到堆中。重复第 3 步,直到堆为空。
  4. 计算最短路径的总长度。因为我们使用的是堆优化的 Dijkstra 算法,所以 $dist[d]$ 存储的就是起始点到目标点的最短路径长度。
代码实现
import heapq

def dijkstra(graph, source, dest):
    n = len(graph)
    dist = [float('inf')] * n
    visited = [False] * n
    dist[source] = 0
    heap = [(0, source)]
    
    while heap:
        (d, u) = heapq.heappop(heap)
        if visited[u]:
            continue
        visited[u] = True
        for v, w in graph[u]:
            if dist[u] + w < dist[v]:
                dist[v] = dist[u] + w
                heapq.heappush(heap, (dist[v], v))
                
    return dist[dest]

# 测试示例
graph = [
    [(1,2), (2,3)],
    [(2,3), (3,4), (4,1)],
    [(3,1), (4,5)],
    [(4,4)],
    [(3,1)]
]
source, dest = 0, 3
print(dijkstra(graph, source, dest))  # Expected output: 3

上面的代码实现了一个基于堆优化的 Dijkstra 算法,在图上查找起始点到目标点的最短路径。其中,输入的图数据是以邻接表的形式给出的。如果你需要在实际应用中使用,还需要根据实际情况做出适当的修改。