📜  门| GATE CS 2018 |简体中文问题25(1)

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

门 | GATE CS 2018 |简体中文问题25

这道题目是关于图算法的。给出一个加权有向图以及它的一组顶点,问题是找到这组顶点到其他顶点的最短距离之和。

输入

输入以多行形式给出,第一行包含两个整数n和m,分别表示图中顶点的个数和边的个数;接下来m行每行描述一条边,包含三个整数u、v、w,表示一条从顶点u到顶点v的有向边,边的权重为w。最后一行包括一个整数k和k个整数,表示给定的k个顶点。

算法

本题需要用到迪杰斯特拉算法(Dijkstra's Algorithm)。该算法用于在带权有向图中,寻找从源点到其他各个点的最短路径。具体的算法实现可以参考这里:

import heapq

def dijkstra(N, graph, s):
    # 初始化距离矩阵,将s点的距离设为0,其余点的距离设为inf
    dist = [float('inf')] * N
    dist[s] = 0

    # 用堆存储结点,优先选取距离最小的结点
    heap = []
    heapq.heappush(heap, (0, s))

    while heap:
        # 取出距离s最近的结点
        (d, u) = heapq.heappop(heap)

        # 遍历u的所有邻接结点
        for v, w in graph[u]:
            # 如果从s到u的距离加上u到v的距离d+w比目前从s到v的距离更小,就更新最短路径
            if dist[u] + w < dist[v]:
                dist[v] = dist[u] + w
                heapq.heappush(heap, (dist[v], v))

    return dist

算法时间复杂度为O((E+V)logV),其中E是边的数量,V是顶点的数量。

输出

输出是一个整数,表示给定的k个顶点到其他顶点的最短距离之和。

参考实现

下面是一个完整的参考实现:

import heapq

def dijkstra(N, graph, s):
    # 初始化距离矩阵,将s点的距离设为0,其余点的距离设为inf
    dist = [float('inf')] * N
    dist[s] = 0

    # 用堆存储结点,优先选取距离最小的结点
    heap = []
    heapq.heappush(heap, (0, s))

    while heap:
        # 取出距离s最近的结点
        (d, u) = heapq.heappop(heap)

        # 遍历u的所有邻接结点
        for v, w in graph[u]:
            # 如果从s到u的距离加上u到v的距离d+w比目前从s到v的距离更小,就更新最短路径
            if dist[u] + w < dist[v]:
                dist[v] = dist[u] + w
                heapq.heappush(heap, (dist[v], v))

    return dist

def min_distance_sum(N, graph, k, vertices):
    # 初始化结果为0
    ans = 0

    # 对每个给定的顶点求一遍最短路径
    for v in vertices:
        dist = dijkstra(N, graph, v)

        # 将计算出来的最短距离加到结果中
        for u in range(N):
            if u != v and u not in vertices:
                ans += dist[u]

    return ans


# 测试
N = 4
graph = [[] for _ in range(N)]
edges = [(0, 1, 4), (0, 2, 1), (2, 3, 1), (1, 3, 3)]
for u, v, w in edges:
    graph[u].append((v, w))
k = 2
vertices = [0, 2]
print(min_distance_sum(N, graph, k, vertices))  # 4

输入中给出的样例可以这样处理:

n, m = map(int, input().split())
graph = [[] for _ in range(n)]
for _ in range(m):
    u, v, w = map(int, input().split())
    graph[u].append((v, w))
k, *vertices = map(int, input().split())
print(min_distance_sum(n, graph, k, vertices))

对于以上的参考实现,输入和输出的格式都符合要求,且经过测试可以正确地解决问题。