📅  最后修改于: 2023-12-03 15:28:46.279000             🧑  作者: Mango
本题考查的是图论的知识。给定一个图,其中包含$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(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]