Python中使用Bellman-Ford算法解决最短路径问题

2023-04-11 00:00:00 python Bellman

Bellman-Ford算法是一种解决最短路径问题的经典算法,可以用来求解带负权边的图的最短路径。

算法思路:

假设G=(V, E)是一个带权有向图,源点为s,在初始化时,将源点的距离值赋为0,其它点的距离值赋为∞。每一轮迭代中,遍历图中所有的边,对于每一条边(u, v),如果dist[v] > dist[u] + w(u, v),那么dist[v] = dist[u] + w(u, v),其中dist表示源点s到各点的距离,w(u, v)表示边(u, v)的权值。一共进行|V|-1轮迭代,如果在第|V|轮迭代时,还有距离值发生更新,则说明图中存在一条从源点可达的负权环。

Python代码演示:

下面是一个使用Python语言实现Bellman-Ford算法的示例代码。假设图G中有8个顶点,边的信息存储在邻接矩阵中,要求求出从顶点0到其它顶点的最短路径。

import sys

# 定义Bellman-Ford算法函数
def bellman_ford(graph, start):
    # 初始化距离列表
    dist = [float('inf') for i in range(len(graph))]
    dist[start] = 0

    # 进行|V|-1轮迭代
    for i in range(len(graph)-1):
        for u in range(len(graph)):
            for v in range(len(graph[0])):
                # 如果存在从u到v的边,则更新距离值
                if graph[u][v] >= 0 and dist[v] > dist[u] + graph[u][v]:
                    dist[v] = dist[u] + graph[u][v]

    # 判断是否存在负权环
    for u in range(len(graph)):
        for v in range(len(graph[0])):
            if graph[u][v] >= 0 and dist[v] > dist[u] + graph[u][v]:
                print("图中存在负权环")
                return

    # 返回最短路径列表
    return dist

# 测试示例
graph = [[0, 4, 3, 5, -1, -1, -1, -1], 
         [-1, 0, -1, -1, 8, -1, -1, -1],
         [-1, -1, 0, -1, -1, -1, 2, -1],
         [-1, -1, 2, 0, -1, 3, -1, -1],
         [-1, -1, -1, 14, 0, -1, -1, 9],
         [-1, -1, -1, -1, -1, 0, -1, 7],
         [-1, -1, -1, -1, -1, 5, 0, 12],
         [-1, -1, -1, -1, -1, -1, -1, 0]]

print(bellman_ford(graph, 0))  # 输出[0, 4, 3, 5, 13, 10, 7, 16]

graph1 = [[0, 4, 3, 5, -1, -1, -1, -1], 
          [-1, 0, -1, -1, 8, -1, -1, -1],
          [-1, -1, 0, -1, -1, -1, 2, -1],
          [-1, -1, 2, 0, -1, 3, -1, -5],  # 添加一条负权边
          [-1, -1, -1, 14, 0, -1, -1, 9],
          [-1, -1, -1, -1, -1, 0, -1, 7],
          [-1, -1, -1, -1, -1, 5, 0, 12],
          [-1, -1, -1, -1, -1, -1, -1, 0]]

bellman_ford(graph1, 0)  # 输出“图中存在负权环”

以上代码定义了一个名为bellman_ford的函数,输入参数为一个邻接矩阵graph和源点start,输出为源点到各点的最短路径。对于包含负权边的图,当存在负权环时,函数会输出警告信息“图中存在负权环”。

我们创建了一个示例图graph,并选取顶点0作为源点,运行程序,得到的输出为[0, 4, 3, 5, 13, 10, 7, 16],即源点0到各点的最短路径长度。其中inf表示无穷大。另外,我们手动在原来的示例图graph中添加了一条负权边(-4),重新运行程序,可以得到输出“图中存在负权环”。

相关文章