BellmanFord算法与SPFA算法

本文介绍了Bellman-Ford算法和SPFA算法,用于求解带权有向图的单源最短路径。Bellman-Ford算法能处理负权边,但时间复杂度较高,适合存在负权回路的情况;SPFA算法是Bellman-Ford的优化版,速度更快,但在有负权回路时可能导致死循环。文章还讨论了两种算法的适用场景和优缺点。
摘要由CSDN通过智能技术生成

​​​​​​

BellmanFord算法与SPFA算法

展开

Bellman-Ford

Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法。该算法由 Richard Bellman 和 Lester Ford 分别发表于 1958 年和 1956 年,而实际上 Edward F. Moore 也在 1957 年发布了相同的算法,因此,此算法也常被称为 Bellman-Ford-Moore 算法。

Bellman-Ford 算法和 Dijkstra 算法同为解决单源最短路径的算法。对于带权有向图 G = (V, E),Dijkstra 算法要求图 G 中边的权值均为非负,而 Bellman-Ford 算法能适应一般的情况(即存在负权边的情况)。一个实现的很好的 Dijkstra 算法比 Bellman-Ford 算法的运行时间要低。

基本概念

负权边:权值为负数的边,称为负权边。

负环:环路中所有边的权值之和为负数,则称该环路为负环。

注意:带负环的图无法求最短路,因为可以沿着负环不停的循环,最短距离为负无穷大。

算法步骤

Bellman-Ford 算法采用动态规划(Dynamic Programming)进行设计,实现的时间复杂度为 O(V*E)O(V∗E),其中 VV 为顶点数量,EE 为边的数量。Dijkstra 算法采用贪心算法(Greedy Algorithm)范式进行设计,普通实现的时间复杂度为 O(V^2)O(V2),若基于堆优化的最小优先队列实现版本则时间复杂度为 O(E + VlogV)O(E+VlogV)。

Bellman-Ford 算法描述:

  1. 创建源顶点 v 到图中所有顶点的距离的集合 dis[]dis[],为图中的所有顶点指定一个距离值,初始均为 ∞∞,源顶点距离为 00;
  2. 计算最短路径,执行 V - 1V−1 次遍历(松弛边);
    • 对于图中的每条边:如果起点 uu 的距离 dd 加上边的权值 ww 小于终点 vv 的距离 dd,则更新终点 vv的距离值 dd;
  3. 检测图中
Bellman-Ford算法是一种用于求解单源最短路径问题的动态规划方法,尤其适用于存在负权边的情况。以下是C语言的一个简单实现: ```c #include <stdio.h> #include <limits.h> #define V 9 // 图的顶点数 // 定义邻接矩阵表示图 int graph[V][V]; void bellman_ford(int src, int dist[]) { int i, j, edge; // 初始化所有顶点到源的距离为无穷大,除了源节点本身为0 for (i = 0; i < V; i++) { if (i == src) dist[i] = 0; else dist[i] = INT_MAX; } // 进行V-1次松弛操作 for (i = 0; i < V - 1; i++) { for (j = 0; j < V; j++) { // 检查是否存在u-v边,并更新距离 for (edge = 0; edge < V; edge++) if (graph[j][edge] && dist[j] != INT_MAX && dist[j] + graph[j][edge] < dist[edge]) dist[edge] = dist[j] + graph[j][edge]; } } // 检查是否有负环,如果存在则会发现不止一次的缩短 for (i = 0; i < V; i++) { for (j = 0; j < V; j++) { if (graph[j][i] && dist[j] != INT_MAX && dist[j] + graph[j][i] < dist[i]) { printf("Graph contains negative weight cycle.\n"); return; } } } } int main() { int src, v, u, w; printf("Enter the number of vertices and edges\n"); scanf("%d", &V); // 输入邻接矩阵 printf("Enter the weighted adjacency matrix:\n"); for (v = 0; v < V; v++) { for (u = 0; u < V; u++) { scanf("%d", &w); graph[v][u] = w; // 如果w非零,则存在从v到u的有向边 } } printf("Source vertex: "); scanf("%d", &src); int dist[V]; // 存储每个顶点到源的最短距离 bellman_ford(src, dist); printf("Shortest path from %d to all other vertices:\n", src); for (v = 0; v < V; v++) { if (dist[v] != INT_MAX) printf("Distance to vertex %d is %d\n", v, dist[v]); else printf("Vertex %d is unreachable\n", v); } return 0; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值