Bellman Ford

可以有负环。
遍历每一条边n-1次,同时更新dis(若无负环则最短路径长度不超过n-1)

#include<stdio.h>
#include<stdlib.h>
#define size 100000
#define sup 0Xffffff0
struct edge {
	int u;
	int v;
	int w;
};
typedef struct edge edge;//边
edge all[size];
int cnt, dis[size];
void insert(int u, int v, int w) {//插入
	all[cnt].u = u, all[cnt].v = v, all[cnt].w = w;
	++cnt;
}
void initial(int n, int s) {//初始化
	for (int i = 1; i <= n; i++) {
		dis[i] = sup;
	}
	dis[s] = 0;
}
int Bellman_Ford(int n, int m, int s) {
	int i, j, k, u, v, w;
	initial(n, s);
	for (i = 0; i < n - 1; i++) {
		for (j = 0; j < m; j++) {
			u = all[j].u, v = all[j].v, w = all[j].w;
			dis[v] = dis[u] + w > dis[v] ? dis[v] : dis[u] + w;
		}
	}
	for (i = 0; i < m; i++) {
		u = all[j].u, v = all[j].v, w = all[j].w;
		if (dis[u] + w < dis[v])return 1;//存在负环
	}
}
int main() {
	int n, m, i, s;
	int u, v, w;
	scanf("%d%d%d", &n, &m, &s);
	for (i = 0; i < m; i++) {
		scanf("%d%d%d", &u, &v, &w);
		insert(u, v, w);
	}
	Bellman_Ford(n, m, s);
	for (i = 1; i <= n; i++)printf("%d ", dis[i]);
}
贝尔曼-福特算法(Bellman-Ford algorithm)是由Richard Bellman和 Lester Ford Jr. 分别在1950年代提出的图论中一种重要的算法。它主要用于解决单源最短路径问题,尤其擅长处理包含负权边(即边的权重可以为负数)的有向图。以下是关于贝尔曼-福特算法的工作原理: 1. **初始化阶段**:首先,给除起始节点之外的所有节点设置一个初始距离值,通常是无穷大(表示尚未找到该节点的最短路径),然后将起始节点的距离设为零。 2. **松弛阶段**:接着,算法会遍历图中的每一条边,尝试更新所有节点的距离值。如果经过一条边的起点到终点的路径长度小于之前已经计算出来的起点到终点的路径长度,则更新终点的距离值。这个过程会被反复执行,直到所有边都被遍历过 `|V| - 1` 次(其中 |V| 表示图中有多少个节点)。这个阶段称为“松弛”步骤,因为算法试图放松节点间的距离约束。 3. **检测负权环**:在最后一步,再次遍历所有的边。如果仍然能找到一条边,其能进一步减少某个节点的最短路径长度,这就意味着图中存在一个负权环(环路中总权重为负),此时算法无法准确计算出所有节点的最短路径。 ### 特点与优势: 1. **处理负权边**:贝尔曼-福特算法最大的特点是它可以处理带负权边的有向图,这是Dijkstra算法所不具备的优势。 2. **发现负权环**:如果图中存在负权环,算法会在最后一次遍历时检测出来,这对于某些特定的应用来说非常有用。 3. **灵活性高**:算法的运行时间和复杂度依赖于图的大小,而不是依赖于边的数量,这意味着即使图中边的数量很多,贝尔曼-福特算法也能有效地工作。 ### 应用场景: - **网络路由**:在互联网和其他通信网络中,贝尔曼-福特算法可以用于计算路由表中的最佳路径,特别是在可能存在临时的负成本(比如优惠折扣)的情况下。 - **资源分配问题**:在一些经济模型或资源调度问题中,可能存在成本随着使用量增加而减少的情况(表现为负斜率的成本函数),贝尔曼-福特算法提供了一种解决方案。 ### 相关问题: 1. **为什么在检测负权环的步骤中再次遍历所有边很重要?** 这是因为在一个有负权环的图中,经过环的路径的总代价总是可以从原来的路径代价中减小。这种可能性直到所有边都经过了`|V|-1`次松弛之后才能得到确认。 2. **贝尔曼-福特算法与Dijkstra算法的主要区别是什么?** 主要区别在于处理负权边的能力。Dijkstra算法不适用于带负权边的图,而贝尔曼-福特算法则可以处理这种情况。 3. **在实际应用中如何评估贝尔曼-福特算法的性能?** 性能评估通常涉及考虑图的密度、边的权重分布、是否存在负权环等因素,以及算法在大规模图集上的稳定性、计算效率等指标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值