📜  所有对最短路径的Johnson算法执行(1)

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

所有对最短路径的Johnson算法执行

算法简介

Johnson算法是一种用于解决所有对最短路径问题的算法。该算法使用了边权重重新计算的技巧,将问题转换为了仅仅需要单源最短路径问题。在对每个源点执行单源最短路径算法之后,我们就可以得到所有对最短路径了。

算法步骤
  1. 添加一个新的节点s,并向原有的图中添加一个从s到每个点的边,边权为0。
  2. 对从s节点开始的所有边进行一次Bellman-Ford算法,得到节点的h值。如果发现存在负环路,则算法停止并返回有负环路的信息。
  3. 对于每个顶点u,对于所有以u为起点的边进行权重重排,得到一个新的边权值w(u,v) = w(u,v) + h(u) - h(v)。
  4. 对每个顶点u,使用Dijkstra算法找出从u到其他所有顶点的最短路径。
  5. 对于任意一条边(u,v),存在路径上的边权w(u,v),通过公式dist(u,v) = w(u,v) + h(v) - h(u)计算出实际的边权值。
代码实现

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

import math
 
def johnson(graph):
    nodes = graph.keys()
    s = 's'
    new_graph = graph.copy()
    for node in nodes:
        new_graph[s][node] = 0
    h = bellman_ford(new_graph, s)
    if not h:
        return None
    for from_node in nodes:
        for to_node in graph[from_node]:
            graph[from_node][to_node] += h[from_node] - h[to_node]
    result = {}
    for node in nodes:
        result[node] = dijkstra(graph, node)
        for target_node in result[node]:
            result[node][target_node] += h[target_node] - h[node]
    return result
 
 
def bellman_ford(graph, start):
    nodes = graph.keys()
    distance = dict.fromkeys(nodes, float('inf'))
    distance[start] = 0
    for i in range(len(nodes) - 1):
        for u in nodes:
            for v in graph[u]:
                new_distance = distance[u] + graph[u][v]
                if distance[v] > new_distance:
                    distance[v] = new_distance
    for u in nodes:
        for v in graph[u]:
            if distance[v] > distance[u] + graph[u][v]:
                return None
    return distance
 
 
def dijkstra(graph, start):
    nodes = graph.keys()
    distance = dict.fromkeys(nodes, float('inf'))
    previous = dict.fromkeys(nodes, None)
    distance[start] = 0
    not_visited_nodes = nodes.copy()
    while not_visited_nodes:
        current = min(not_visited_nodes, key=lambda x: distance[x])
        not_visited_nodes.remove(current)
        for neighbour in graph[current]:
            new_distance = distance[current] + graph[current][neighbour]
            if new_distance < distance[neighbour]:
                distance[neighbour] = new_distance
                previous[neighbour] = current
    return distance
总结

Johnson算法是一种用于解决所有对最短路径问题的算法。它通过重新计算边权重的方式,将问题转换为单源最短路径问题,最后再对每个源点执行单源最短路径算法,得到所有对最短路径。虽然算法的时间复杂度为O(V^2logV+ElogV),但它可以处理负权边和负环路的问题,因此在实际应用中仍然具有重要的价值。