📌  相关文章
📜  图中从源 S 到目标 D 的最短路径,对于多个查询,恰好有 K 条边(1)

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

最短路径查询

该程序用于寻找图中从源点 S 到目标点 D 的最短路径,同时满足该路径恰好有 K 条边。

输入格式

输入为一个有权有向图,其中每条边的权值均为正整数。第一行包含三个正整数,分别为节点总数 n,起点 S,终点 D。接下来若干行,每行描述一条边,其中三个正整数 u,v,w 分别表示起点,终点,边权。

输出格式

输出一个整数,表示满足条件的最短路径长度,如果不存在满足条件的路径,则输出 -1。

算法实现

该程序使用了 Dijkstra 算法来计算最短路径。在每次更新每个节点的距离时,需要记录经过的边数。同时,由于每条边的长度均为正数,我们可以使用优先队列来维护候选节点。具体实现过程如下:

  1. 初始化:将起点 S 加入队列,并将 S 到它本身的最短路径长度初始化为 0,其余点到 S 的最短路径长度初始化为正无穷,边数初始化为 0。
  2. 从队列中取出距离 S 最近的点 u,并将该点标记为已经访问。
  3. 对于 u 的每条出边,更新每个节点的距离和边数。如果该点没有被访问过,则将该点加入队列。
  4. 如果我们得到了目标节点 D,并且路径中恰好包含 K 条边,就返回当前距离;否则继续执行步骤 2。

以下是使用 Python 代码实现的 Dijkstra 算法:

import heapq

def dijkstra(graph, start, end, k):
    # 先将起点加入队列,并初始化距离和边数
    queue = [(0, start, 0)]
    distances = {v: float('inf') for v in graph}
    edges = {v: 0 for v in graph}
    distances[start] = 0
    
    while queue:
        # 取出队列中最小距离的节点
        curr_dist, node, curr_edge = heapq.heappop(queue)
        # 如果该节点已经被访问,则跳过
        if curr_dist > distances[node]:
            continue
        # 遍历当前节点的出边
        for neighbor, weight in graph[node].items():
            # 更新邻居节点的距离和边数
            distance = curr_dist + weight
            edge = curr_edge + 1
            if distance < distances[neighbor] and edge <= k:
                distances[neighbor] = distance
                edges[neighbor] = edge
                # 将邻居节点加入队列
                heapq.heappush(queue, (distance, neighbor, edge))
        # 如果已经到达目标节点,并且路径中包含 K 条边,就返回当前距离
        if node == end and edges[node] == k:
            return distances[node]
    
    # 如果无法到达目标节点,或者无法找到恰好包含 K 条边的路径,则返回 -1
    return -1
示例

输入:

5 0 4
0 1 1
1 2 2
2 3 3
3 4 4
0 2 2
2 4 2

输出:

7

解释:

令 K=2,该图的最短路径为 0->2->4,长度为 7。