欢迎访问宙启技术站
智能推送

Bellman-Ford算法的原理与实现

发布时间:2024-01-10 12:53:28

Bellman-Ford算法是一种用于解决带有负权边的最短路径问题的算法。与Dijkstra算法不同,Bellman-Ford算法可以处理负权边,因此更加通用。

算法原理:

1. 创建一个距离数组dist,用于存储从源节点到其它节点的最短距离。将源节点的距离初始化为0,其它节点的距离初始化为无穷大。

2. 对于图中的每一条边(u, v, w),循环遍历,将通过中间节点u到达节点v的距离更新为dist[v] = min(dist[v], dist[u]+w)。其中w为u到v的边的权重。

3. 重复上述步骤,直到没有边需要更新距离或者进行n-1次迭代(n为节点数量)。

4. 最后检查是否存在负环路。如果在第n次迭代后,还存在边可以更新距离,说明存在负环路。这是因为一个图的最短路径最多只能经过n-1条边,如果存在n条边进行距离更新,则说明存在负环路。

算法实现:

import sys

class Graph:
    def __init__(self, vertices):
        self.V = vertices
        self.graph = []
        
    def add_edge(self, u, v, w):
        self.graph.append((u, v, w))
        
    def print_solution(self, dist):
        print("Vertex Distance from Source")
        for i in range(self.V):
            print(f"{i}\t\t{dist[i]}")
    
    def bellman_ford(self, src):
        dist = [float("Inf")] * self.V
        dist[src] = 0
        
        # Relax all edges |V| - 1 times
        for _ in range(self.V - 1):
            for u, v, w in self.graph:
                if dist[u] != float("Inf") and dist[u] + w < dist[v]:
                    dist[v] = dist[u] + w
        
        # Check for negative-weight cycles
        for u, v, w in self.graph:
            if dist[u] != float("Inf") and dist[u] + w < dist[v]:
                print("Graph contains negative-weight cycle")
                return
        
        self.print_solution(dist)

使用例子:

g = Graph(5)
g.add_edge(0, 1, -1)
g.add_edge(0, 2, 4)
g.add_edge(1, 2, 3)
g.add_edge(1, 3, 2)
g.add_edge(1, 4, 2)
g.add_edge(3, 2, 5)
g.add_edge(3, 1, 1)
g.add_edge(4, 3, -3)

g.bellman_ford(0)

输出结果:

Vertex Distance from Source
0		0
1		-1
2		2
3		-2
4		1

上述例子中,我们创建了一个包含5个节点的图。通过调用add_edge方法添加边。最后通过调用bellman_ford方法计算从源节点0到其它节点的最短距离。在输出结果中,每一行表示从源节点到对应节点的最短距离。

Bellman-Ford算法时间复杂度为O(V*E),其中V为节点数量,E为边数量。