最短路 Bellman-Ford(贝尔曼-福特)

Bellman-Ford(边权可正可负)

Bellman-Ford算法的迭代松弛操作,实际上就是按顶点距离s的层次,逐层生成这棵最短路径树的过程。

在对每条边进行1遍松弛的时候,生成了从s出发,层次至多为1的那些树枝。也就是说,找到了与s至多有1条边相联的那些顶点的最短路径;对每条边进行第2遍松弛的时候,生成了第2层次的树枝,就是说找到了经过2条边相连的那些顶点的最短路径……。因为最短路径最多只包含n-1 条边,所以,只需要循环n-1 次。

如果最短路存在,则一定不含环:

1.存在零环或正环,则去掉环路径不会变长

2.存在负环,则只要绕着环走,路径只会越来越短,下界不收敛,不存在最短路

最短路只包含n-1个结点(不包含起点)

操作步骤:

第一,初始化所有点。每一个点保存一个值,表示从原点到达这个点的距离,将原点的值设为0,其它的点的值设为无穷大(表示不可达)。

第二,进行循环,循环下标为从1到n-1(n等于图中点的个数)。在循环内部,遍历所有的边,进行松弛计算。

第三,遍历途中所有的边(edge(u,v)),判断是否存在这样情况:

d(v) > d (u) + w(u,v)说明无法向下收敛

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define inf 0x7ffffff

struct Edge
{
    int u,v,cost;
}edge[2000];

int pre[200];//父亲

int dis[200];//到源点的距离

int n,m,src;//点的个数,边数,源点

bool relax(int u,int v,int cost)//对边进行松弛
{
    if(dis[v]>dis[u]+cost)
    {
        dis[v]=dis[u]+cost;
        return true;//成功松弛
    }
    return false;//没有松弛成功
}

int Bellman_Ford()
{
    int i,j,flag;
    for(i=1;i<=n;i++) dis[i]=(i==src? 0:inf);//第一步:初始化dis
    for(i=1;i<n;i++)//第二步:进行 n-1次迭代,每次对所有边进行松弛
    {
        flag=0;
        for(j=0;j<m;j++)
        {
            if(relax(edge[j].u,edge[j].v,edge[j].cost))
            {
                pre[v]=u;//记录路径
                flag=1;
            }
        }
        if(!flag) break;//所有的边都没有松弛成功
    }
    for(i=0;i<m;i++)//第三步:如果能够继续松弛,说明下界不收敛,存在负环
    {
        if(relax(edge[i].u,edge[i].v,edge[i].cost))
        {
            return 0;
        }
    }
    return 1;
}

int main()
{
    int i,j;
    while(~scanf("%d%d%d",&n,&m,&src))
    {
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].cost);//输入每条边的 左右端点,权值
        }
        if(Bellman_Ford())
        {
            for(i=1;i<=n;i++)
            {
                printf("%d\n",dis[i]); //输出各个点到源点的距离
            }
        }
        else printf("have negative circle\n");

    }
    return 0;
}

输入案例1.

4 6 1

1 2 20

1 3 5

4 1 -200

2 4 4

4 2 4

3 4 2

输入案例2.

4 6 1

1 2 2

1 3 5

4 1 10

2 4 4

4 2 4

3 4 2

最短路 Bellman-Ford(贝尔曼-福特)

时间: 2024-10-02 23:56:26

最短路 Bellman-Ford(贝尔曼-福特)的相关文章

oj2894(贝尔曼福特模板)

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2894 就因为粗心,一中午没A,题目说是2000000条边无向图,我数组却开了2000000真是该死,我一看别人A的状态,内存都比我大一倍,瞬间知道自己手残了,明明是4000000啊, 但令我不解的是说SPFA是BE的改良版,但为什么7100ms,虐心,完全坑爹. #include <iostream> #include <stdio.h

贝尔曼福特算法

有边数限制,存在负权值,的最短路问题,一般用bellmanford算法: 给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数. 请你求出从1号点到n号点的最多经过k条边的最短距离,如果无法从1号点走到n号点,输出impossible. 注意:图中可能 存在负权回路 . 输入格式 第一行包含三个整数n,m,k. 接下来m行,每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z. 输出格式 输出一个整数,表示从1号点到n号点的最多经过k条边的最短距离. 如果不存

【算法日记】贝尔曼-福德算法

如上图使用Dijkstra算法将无法获取到最短路径 1.A->C->D   5 2.A->B...没有 最近路径为5.但是实际上B->C的路径为-2. A->B->C->D的最短开销为3 Dijkstra算法无法判断含负权边的图的最短路.如果遇到负权,在没有负权回路存在时(负权回路的含义是,回路的权值和为负.)即便有负权的边,也可以采用贝尔曼-福德算法算法正确求出最短路径. 算法实现 1 def bellman_ford( graph, source ): 2 3

ACM/ICPC 之 最短路径-Bellman Ford范例(POJ1556-POJ2240)

两道Bellman Ford解最短路的范例,Bellman Ford只是一种最短路的方法,两道都可以用dijkstra, SPFA做. Bellman Ford解法是将每条边遍历一次,遍历一次所有边可以求得一点到任意一点经过一条边的最短路,遍历两次可以求得一点到任意一点经过两条边的最短路...如 此反复,当遍历m次所有边后,则可以求得一点到任意一点经过m条边后的最短路(有点类似离散数学中邻接矩阵的连通性判定) POJ1556-The Doors 初学就先看POJ2240吧 题意:求从(0,5)到

POJ 1860 Currency Exchange (Bellman ford)

Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 22405   Accepted: 8095 Description Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and pe

Bellman - Ford 算法解决最短路径问题

Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力不从心了,而Bellman - Ford算法可以解决这种问题. Bellman - Ford 算法可以处理路径权值为负数时的单源最短路径问题.设想可以从图中找到一个环路且这个环路中所有路径的权值之和为负.那么通过这个环路,环路中任意两点的最短路径就可以无穷小下去.如果不处理这个负环路,程序就会永远运

Bellman—Ford算法思想

---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G运行Bellman—Ford算法的结果是一个布尔值,表明图中是否存在着一个从源点s可达的负权回路.若存在负权回路,单源点最短路径问题无解:若不存在这样的回路,算法将给出从源点s到图G的任意顶点v的最短路径值d[v] Bellman—Ford算法流程 分为三个阶段: (1)初始化:将除源点外的所有顶点

蓝桥杯 算法训练 最短路 [ 最短路 bellman ]

传送门 算法训练 最短路 时间限制:1.0s   内存限制:256.0MB 锦囊1 锦囊2 锦囊3 问题描述 给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环).请你计算从1号点到其他点的最短路(顶点从1到n编号). 输入格式 第一行两个整数n, m. 接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边. 输出格式 共n-1行,第i行表示1号点到i+1号点的最短路. 样例输入 3 3 1 2 -1 2 3 -1 3 1 2 样例输出 -1 -2 数据规

算法复习:最短路Dijkstra - Ford - Floyd

Dijkstra算法适用范围是单源最短路,有向图或者无向图,不能处理负权值 Floyd算法适用多源最短路,有向图或者无向图,可以处理负权值但是不能处理负权回路 Ford 算法多源最短路,可以处理负权值,能检测负权回路 Leetcode 743. 网络延迟时间 先用Dijkstra算法解,输入是vector要转存一下,另外找的是最后一个传播到的节点所用时间 #define max 999999 #define CLR(donser,value) memset(donser,value,sizeof