C++基础算法10:Bellman_Ford

1、概念

Bellman-Ford(贝尔曼-福特)算法是一个用于单源最短路径问题的经典算法,能够处理带负权边的图,是图论中非常重要的算法之一。

2、实战例子

给定n个节点,m条边。可能存在重环,权重可能为负数。

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 1e5 + 10;
int n, m, k, d[N], me[N];  // d存储源点到节点的最短路径;me暂存当前的路径数组
struct Edge {
    int a, b, w;
} in[N];

bool bell_ford() {
    fill(d, d + N, 0x3f3f3f3f);  // 初始化为无穷大
    d[1] = 0;  // 源点到自身距离为 0
    for (int i = 0; i < k; ++i) {
        memcpy(me, d, sizeof(d));  // 备份当前的最短路径
        for (int j = 0; j < m; ++j) {
            int a = in[j].a, b = in[j].b, w = in[j].w;
            d[b] = min(d[b], me[a] + w);  // 松弛操作
        }
    }
    return d[n] <= 0x3f3f3f3f / 2;  // 若目标节点距离大于无穷大,返回 false
}

int main() {
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 0; i < m; ++i) {
        scanf("%d%d%d", &in[i].a, &in[i].b, &in[i].w);
    }
    if (bell_ford()) 
        cout << d[n];  // 输出最短路径
    else 
        puts("impossible");  // 输出不可达
    return 0;
}

使用 me[] 是为了避免在一轮松弛中读取到“被修改后的值”,保证每次松弛都严格依赖上一次完整的结果,从而保证 Bellman-Ford 算法的正确性。

3、Dijkstra为什么解决不了负数权重的问题?

在Dijkstra算法中,每次都会选择一个当前最短的未处理节点,并且假设这个节点到达其他节点的路径不会再变得更短。该算法认为,当某个节点的最短路径确定后,后续不会有更短的路径通过该节点。这在所有边权都为非负数时是正确的,因为你只会逐步增加路径的长度,但不会出现路径长度突然减少的情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值