📌  相关文章
📜  门| Sudo GATE 2020 Mock II(2019年1月10日)|第55章(1)

📅  最后修改于: 2023-12-03 14:58:33.299000             🧑  作者: Mango

门| Sudo GATE 2020 Mock II(2019年1月10日)|第55章

本题是GATE 2020模拟试题中的第55章,出题者为Sudo Mock II。这道题目要求考生实现一个程序,该程序用于查找图中的最短路径。

题目描述

给定一个图和其中的两个节点,求这两个节点之间的最短路径。

输入格式

输入文件的第一行包含两个整数 $n$ 和 $m$,表示节点数和边数。

接下来 $m$ 行,每行两个整数 $u$ 和 $v$,表示一条从节点 $u$ 向节点 $v$ 的无向边。

输入文件的最后一行包含两个整数 $s$ 和 $t$,表示起点和终点。

输出格式

输出文件的第一行为最短路径的长度。

第二行为沿着最短路径从起点到终点所经过的所有节点,以空格分隔。

样例输入
7 9
1 2
1 3
1 4
2 3
3 4
3 5
4 6
5 6
6 7
1 7
样例输出
3
1 4 6 7
思路分析

这是一道求最短路径的问题,很自然的就可以想到使用Dijkstra算法进行解决。Dijkstra算法的时间复杂度为 $O(E\log{V})$,其中 $V$ 表示节点数,$E$ 表示边数。

代码实现

我们可以通过实现以下步骤来完成本题:

  • 对于每个点,初始化它的path长度为无限大来表示它是不可达的。
  • 对于要求的起点,设置为0。之后遍历其所有的邻居,把从起点到该邻居的距离(即路径长度)存储在该邻居的path中。
  • 选出现有path中最小的值作为下一个要访问的点,并将其设置为访问状态。若下一个点已在访问状态,则跳过此步,继续选取下一个点。
  • 遍历下一个点的所有邻居,将这些邻居与起点间的路径长度和其原path长度比较。若总长度更短,则更新邻居的path。
  • 重复步骤三,直到目标点被选中为止。

下面是一个简单的实现示例(使用python语言):

import heapq

def dijkstra(start, end):
    heap, visited = [(0, start, [])], set()
    while heap:
        (cost, vertex, path) = heapq.heappop(heap)
        if vertex not in visited:
            visited.add(vertex)
            path = path + [vertex]
            if vertex == end: return (cost, path)
            for i in graph[vertex]:
                if i[0] not in visited:
                    heapq.heappush(heap, (cost+i[1], i[0], path))
    return float("inf")

# 接收输入
n, m = map(int, input().split())
graph = [[] for i in range(n)]
for i in range(m):
    x, y = map(int, input().split())
    graph[x-1].append((y-1, 1))

start, end = map(int, input().split())
# 求解最短路径
cost, path = dijkstra(start-1, end-1)
# 输出路径长度和节点路径
print(cost)
print(*[i+1 for i in path])

本代码中使用一个堆(heap)来维护到达每个节点的总长度,并依此选取下一个节点进行探索。可以看到,这个实现非常简单,而且已经能够通过测试数据。真正搞明白堆的原理,代码优化就可以打造的更完美了。