题目描述
小明是蓝桥王国的王子,今天是他登基之日。
在即将成为国王之前,老国王给他出了道题,他想要考验小明是否有能力管理国家。
题目的内容如下:
蓝桥王国一共有N个建筑和M条单向道路,每条道路都连接着两个建筑,每个建筑都有自己编号,
分别为1~N。(其中皇宫的编号为1)从皇宫到每个建筑的最短路径是多少?
经过你的帮助,小明轻松的回答了该问题,但是国王的考验并不仅仅这么简单。很快国王又提出了
一个问题,他要小明回答从建筑S到建筑T的第K短路的长度为多少?
小明此时已经失去了思考能力,作为他的好朋友,请你再次帮帮他。
输入描述
输入第一行包含三个正整数N, M 。
第2到M+1行每行包含三个正整数u,v, w,表示u→ v之间存在一条距离为w的路。
第M+2行包含三个正整数S,T,K。
1 ≤s,T≤N≤10^3,1 ≤ m ≤10^5,1 ≤ui, vi ≤N,0≤wi≤ 10^3,保证S≠ T。
输出描述
输出占一行,包含一个整数,表示S→T的第K短路的长度,如果第K短路不存在,则输出-1。
输入输出样例
实例1
输入
输出
实例2
输入
输出
运行限制
- 最大运行时间:1s
- 最大运行内存:128M
主要思路 :(个人理解)
-
构建图:根据输入的道路信息,创建一个邻接表表示的图。图的节点是建筑,每个节点的邻居是与其相连的建筑以及对应的道路权重。
-
实现函数:该函数使用堆(heapq)来实现 Dijkstra 算法,以计算从起点到终点的前K短路径。堆中的元素是三元组 ,分别表示到达节点、路径花费、当前路径。
-
主函数调用:读取输入,包括建筑数量N、道路数量M、道路信息roads、起点S、终点T和目标路径序号K。然后调用 函数,得到结果并输出。
总体来说,代码采用了 Dijkstra 算法来计算最短路径,使用堆来维护当前可能的最短路径,并通过遍历邻居节点来不断更新堆中的路径信息。最终,通过检查找到的路径列表,返回第K短路径的长度或者 -1(如果第K短路径不存在)。
关键代码:
import os
import sys
import heapq
# 用于实现堆数据结构
def kth_shortest_path(N, M, roads, S, T, K):
graph = [[] for _ in range(N + 1)]
# 创建空列表表示建筑之间的图
for u, v, w in roads:
graph[u].append((v, w))
# 将道路信息加入图中,表示从建筑u到建筑v存在一条边,边的权重为w
def k_shortest_paths(start, end, k):
# 计算从起点到终点的前K短路径
heap = [(0, start, [])]
visited = set()
# 创建集合跟踪已访问的节点,防止重复访问
paths = []
# 创建空列表,存储找到的路径
while heap:
# 循环直到堆为空
cost, node, path = heapq.heappop(heap)
if node == end:
# 当前节点是终点
paths.append((cost, path))
if len(paths) == k:
# 如果已经找到k条路径结束循环
return paths
if node not in visited:
# 没有被访问
visited.add(node)# 将当前节点标记为已访问
for neighbor, edge_cost in graph[node]:
# 遍历当前节点的邻节点和对应边权重
heapq.heappush(heap, (cost + edge_cost, neighbor, path + [(node, neighbor)]))
return paths
kth_paths = k_shortest_paths(S, T, K)
return kth_paths[K - 1][0] if K <= len(kth_paths) else -1
if __name__ == "__main__":
N, M = map(int, input().split())
# 输入建筑数量N和道路数量M
roads = [tuple(map(int, input().split())) for _ in range(M)]
# 输入M条道路的具体信息。
S, T, K = map(int, input().split())
# 输入起点S、终点T和目标路径序号K
result = kth_shortest_path(N, M, roads, S, T, K)
print(result)
悟以往之不谏,知来者之可追!!