import heapq import sys INT_INF = 0x7fffffff class GraphMatrix: def __init__(self, size: int): self.vertices = size self.matrix = [[[] for _ in range(size)] for _ in range(size)] def add_edge(self, start: int, end: int, weight: int = 1): self.matrix[start][end].append(weight) def get_edge(self, start: int, end: int, invert: bool = False) -> list[int]: if invert: return self.matrix[end][start] else: return self.matrix[start][end] def get_edge_min(self, start: int, end: int, invert: bool = False) -> int: return min(self.get_edge(start, end, invert)) def get_adjacent_vertices(self, vertex: int, invert: bool = False) -> list[int]: return [i for i in range(self.vertices) if self.get_edge(vertex, i, invert)] def __repr__(self): return "\n".join([" | ".join(map(str, row)) for row in self.matrix]) class VertexNode: def __init__(self, vertex: int, cost: int, heuristic_cost: int = 0): self.vertex = vertex self.cost = cost self.heuristic_cost = heuristic_cost @property def evaluated_cost(self): return self.heuristic_cost + self.cost def __lt__(self, other): return self.evaluated_cost < other.evaluated_cost def __repr__(self): return f"#{self.vertex}(g={self.cost},h={self.heuristic_cost})" def dijkstra_init(graph: GraphMatrix, end: int) -> dict[int, int]: open_list: list[VertexNode] = [] heuristic_map: dict[int, int] = {} visited: set[int] = set() heuristic_map[end] = 0 heapq.heappush(open_list, VertexNode(end, 0)) while open_list: current_node = heapq.heappop(open_list) if current_node.vertex in visited: continue visited.add(current_node.vertex) for next_vertex in graph.get_adjacent_vertices(current_node.vertex, True): if next_vertex in visited: continue new_cost = current_node.cost + graph.get_edge_min(current_node.vertex, next_vertex, True) # 如果新路径更短,或者该节点第一次被访问 if new_cost < heuristic_map.get(next_vertex, INT_INF): heuristic_map[next_vertex] = new_cost heapq.heappush(open_list, VertexNode(next_vertex, new_cost)) return heuristic_map def a_star_solve(graph: GraphMatrix, start: int, end: int, count: int, heuristic_map: dict[int, int]) -> list[int]: open_list: list[VertexNode] = [] # 此处不是「visited_record」!我们要记录所有访问,只是不需要展开过多。 # 因此也不需要「更新 g 值,因为我们记录了一切 g 的节点! # 逻辑是:1. 每条最短路径上的每个节点一定是被 expand 过的;2. 可采用的 h 可保证先找更短路 expanded_record: dict[int, int] = {} # node_record: dict[int, VertexNode] = {} original_node = VertexNode(start, 0, heuristic_map.get(start, INT_INF)) heapq.heappush(open_list, original_node) # node_record[start] = original_node result_list: list[int] = [] while open_list: # print(open_list, file=sys.stderr) current_node = heapq.heappop(open_list) expanded_record[current_node.vertex] = expanded_record.get(current_node.vertex, 0) + 1 # print(current_node, open_list, file=sys.stderr) if current_node.vertex == end: result_list.append(current_node.cost) if len(result_list) >= count: return result_list if expanded_record.get(current_node.vertex, 0) > count: continue # 不扩展,剪枝 for next_vertex in graph.get_adjacent_vertices(current_node.vertex): for edge_weight in graph.get_edge(current_node.vertex, next_vertex): next_node = VertexNode( next_vertex, current_node.cost + edge_weight, heuristic_map.get(next_vertex, INT_INF) ) heapq.heappush(open_list, next_node) return result_list if __name__ == '__main__': vertices_count, edge_count, result_count = map(int, input().split()) graph = GraphMatrix(vertices_count + 1) for _ in range(edge_count): start, end, weight = map(int, input().split()) graph.add_edge(start, end, weight) # print(graph, file=sys.stderr) heuristic_map = dijkstra_init(graph, 1) print(heuristic_map, file=sys.stderr) result_list = a_star_solve(graph, vertices_count, 1, result_count, heuristic_map) # print(result_list, file=sys.stderr) result_list += [-1] * (result_count - len(result_list)) print(*result_list, sep="\n")