📜  贝尔曼·福特算法(1)

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

贝尔曼-福特算法介绍

简介

贝尔曼-福特算法(Bellman-Ford algorithm)是一种用于求解单源最短路径的算法,可以处理有向图或负权边的情况。算法的基本思想是依次对图中的所有边进行松弛操作(如果存在一条从顶点u到顶点v的边,那么对于任意的边权w(u,v),我们有d[v]<=d[u]+w(u,v)),如果经过一轮松弛操作后,每个顶点的最短路径已经求出,那么算法结束。

算法流程
  1. 初始化:将除了起点之外的所有顶点的最短距离d设置为正无穷 (∞),起点的最短距离d为0。
  2. 对所有边进行一次松弛操作,即对于每条边(u,v),如果d[u]+w(u,v)<d[v],则更新d[v]=d[u]+w(u,v),其中w(u,v)表示边(u,v)的权值。
  3. 如果经过一轮松弛操作后,没有更新任何一个顶点的最短距离,则算法结束。
  4. 否则重复步骤2-3。

如果图中存在从源点可达的负权回路,则算法会进入无穷循环。

代码实现

以下为C++实现的Bellman-Ford算法代码片段:

const int INF = 0x3f3f3f3f;

struct Edge {
    int u, v, w;
};

Edge edges[M];
int d[N]; // d[i]表示从源点s到i的最短距离

void bellman_ford(int s, int n, int m) {
    memset(d, INF, sizeof(d));
    d[s] = 0;
    for (int i = 1; i <= n - 1; i++) {
        bool updated = false;
        for (int j = 0; j < m; j++) {
            int u = edges[j].u, v = edges[j].v, w = edges[j].w;
            if (d[u] != INF && d[u] + w < d[v]) {
                d[v] = d[u] + w;
                updated = true;
            }
        }
        if (!updated)
            break;
    }
}
时间复杂度

Bellman-Ford算法的时间复杂度为O(nm),其中n为图中顶点数,m为边数。

总结

贝尔曼-福特算法是一种计算单源最短路径的算法,可以处理负权边和有向图的情况。但其时间复杂度较高,因此在实际应用中不如Dijkstra算法。同时,对于存在负权回路的图,该算法无法求得最短路径(因为不存在最短路径)。