📌  相关文章
📜  门| Sudo GATE 2020 Mock I(2019年12月27日)|问题9(1)

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

门| Sudo GATE 2020 Mock I(2019年12月27日)|问题9

简介

本题考查的是图论的知识。给定一个图,其中包含$n$个顶点和$m$条边,每条边有一个权重,需要从指定的起点到达指定的终点,要求经过的边的总权重之和最小。可以使用Dijkstra算法或者最小生成树算法解决此问题。

输入

输入数据的第一行包含三个整数$n, m, q$,分别表示图中顶点的个数、边数、问题的个数。

接下来$m$行,每行包含三个整数$a, b, w$,表示存在$a$和$b$之间的一条边,其权重为$w$。

接下来$q$行,每行包含两个整数$s, t$,分别表示问题的起点和终点。

输出

对于每个问题,输出到达终点的最小权重和。如果无法到达,则输出$-1$。

示例

输入:

4 4 2
1 2 1
1 3 4
2 4 7
3 4 2
1 4
2 3

输出:

8
4
算法

可以考虑使用Dijkstra算法或最小生成树算法。其中,Dijkstr算法的时间复杂度为$O(m\log n)$,适用于边比较稠密的图;最小生成树算法的时间复杂度为$O(m\log m)$,适用于边比较稀疏的图。实际应用中,需要注意图中是否存在负权边,如果存在,需要使用Bellman-Ford算法。

伪代码
Dijkstra算法
Dijkstra(G, s, t):
    S = []
    d = [inf]*len(G) # 保存每个顶点到起点的最短路
    d[s] = 0        # 起点到起点的距离为0
    heap = [(0, s)] # 以元组(距离, 顶点)的形式保存到达未确定最短路的顶点的距离和编号
    while heap:
        dist, u = heapq.heappop(heap)
        S.append(u)
        if u == t:  # 已经到达终点
            break
        for v, w in G[u]:
            if v not in S:  # 如果v已经被处理过,则跳过
                if d[v] > d[u] + w:
                    d[v] = d[u] + w
                    heapq.heappush(heap, (d[v], v))
    if d[t] == inf:
        return -1
    else:
        return d[t]
最小生成树算法
Kruskal(G, s, t):
    edges.sort()
    num = 0
    weights = 0
    parent = list(range(n))
    for e in edges:
        if find(parent, e[0]) != find(parent, e[1]):
            num += 1
            weights += e[2]
            parent[find(parent, e[0])] = find(parent, e[1])
            if num == n - 1:
                break
    return weights

def find(parent, i):
    if parent[i] == i:
        return i
    else:
        parent[i] = find(parent, parent[i])
        return parent[i]
参考资料