Bellman-Ford(最短路)

bellmen-ford算法,与dijkstra不同,bellman-ford可以运用于有负权值的图,不过复杂度很高,O(N*M )… 慎用~(可以用SPFA,它bwllman-ford的扩展)
Bellman-ford算法同样是对每条边进行N-1次松弛,当有权值为负时,对所有边进行N-1次松弛,如果dis还能更新,说明有负环。
ps:名词解释【负环】 在一个图里每条边都有一个权值(有正有负)
如果存在一个环(从某个点出发又回到自己的路径),而且这个环上所有权值之和是负数,那这就是一个负权环,也叫负权回路
存在负权回路的图是不能求两点间最短路的,因为只要在负权回路上不断兜圈子,所得的最短路长度可以任意小。
Bellman-ford原理:
1.如果最短路存在,则每个顶点最多经过一次,因此不超过n-1条边;
2.长度为k的路由长度为k-1的路加一条边得到;
3.由最优性原理,只需依次考虑长度为1,2,…,k-1的最短路。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int inf=0x3f3f3f3f;
int main()
{
    int i,k,n,m;
    int u[10],v[10],w[10],dis[10];
    scanf("%d%d",&n,&m);
    for(i=1; i<=n; i++)
        scanf("%d%d%d",&u[i],&v[i],&w[i]); 
    for(i=0; i<=n; i++)
        dis[i]=inf;
    dis[1]=0;
    int flag;
    for(k=1; k<n; k++)
    {
        flag=0; //标记dis数组会不会变化
        //进行一轮松弛
        for(i=1; i<=m; i++)
        {
            if(dis[v[i]]>dis[u[i]]+w[i]) //表示u[i]->v[i]这条边的值+1号顶点到u[i]点的值是否小于原来1号顶点到u[i]点的值
            {
                dis[v[i]]=dis[u[i]]+w[i];
                flag=1;//dis数组更新
            }
        }
        if(flag==0) break; //表示数组松弛完毕
    }
    flag=0; //检验是否会出现负环
    for(i=1; i<=m; i++)
        if(dis[v[i]]>dis[u[i]]+w[i]) flag=1; //若还能松弛则存在负环
    if(flag==0)
    {
        for(i=1; i<=n; i++)
            printf("%d ",dis[i]);
        printf("\n");
    }
    else
        printf("此图存在负环回路\n");

    return 0;
}

Bellman-Ford 算法往往不到n-1轮就已经松弛完毕,用标记变量可以减少循环次数。
在这个算法中加入队列进行优化就是SPFA算法,等看懂了在写一下。

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/wxw15617488718/article/details/76448598
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞