📜  门| GATE-CS-2003 |问题 21(1)

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

门 | GATE-CS-2003 | 问题 21

本题是GATE-CS-2003的第21个问题,考察的是图形算法的实现能力。

题目描述

给定一张无向图和一个起点,对于图中每个点,计算它到起点的最短距离。图中存在负权边和自环。

输入格式
  • 输入的第一行包含两个整数,分别为 nm,表示图有 n 个节点和 m 条边。
  • 接下来 m 行,每行三个整数 uvw,表示一条从节点 u 到节点 v 权重为 w 的无向边。
  • 输入的最后一行包括一个整数,表示起始点的节点编号。
输出格式

输出 n 行,第 i 行表示节点 i 到起点的最短距离。

示例

输入:

5 5
1 2 5
2 3 2
3 4 4
4 5 1
5 1 1
1

输出:

0
5
7
11
12
实现思路

该问题可以通过Dijkstra算法或Bellman-Ford算法求解。这里以Dijkstra算法为例进行介绍。

Dijkstra算法是基于贪心思想的单源最短路径算法,用来求一张图中一个节点到其他所有节点的最短路径。算法维护一个集合 S,表示已经求出最短路径的节点集合,初始时 S 中只包括起点。之后,每次选取一个距离起点最近的、且不在 S 中的点,把它加入 S 中,并用它更新与它相邻的其他节点的距离。这样,不断重复以上过程,直到把所有点都加入集合 S 中为止。

Dijkstra算法存在一个优先队列优化的实现,可以进一步加速算法的执行速度。

代码实现

以下是Dijkstra算法的完整实现,使用了优先队列优化。时间复杂度为 $O(m\log n)$。

import heapq

def dijkstra(n, m, graph, start):
    distances = [float('inf')] * n
    distances[start] = 0

    visited = [False] * n
    visited[start] = True

    heap = [(0, start)]

    while heap:
        (dist, node) = heapq.heappop(heap)

        visited[node] = True

        for i, weight in graph[node]:
            if visited[i]:
                continue

            if distances[node] + weight < distances[i]:
                distances[i] = distances[node] + weight
                heapq.heappush(heap, (distances[i], i))

    return distances

n, m = map(int, input().split())

graph = [[] for _ in range(n)]

for _ in range(m):
    u, v, w = map(int, input().split())
    graph[u-1].append((v-1, w))
    graph[v-1].append((u-1, w))

start = int(input()) - 1

distances = dijkstra(n, m, graph, start)

for d in distances:
    print(d)
总结

通过本题的实现,我们学习了Dijkstra算法的实现思路和代码实现。同时,我们也学习了图形算法中的贪心思想,对图形算法的理解和实现有了更深入的认识。