图论-Bellman-Ford

上次我们学习了Dijkstra,其有一个不错的时间复杂度上限:O(n log n),但其对于负权边的处理会出错啦

一个简单的小例子:

这个图中如果我们发现以3号点为原点,跑一边dijkstra的话

我们先会取2号点进入原点集合,再取一号点。这样得到的dist[2]=3,dist[1]=4

错!

我们很容易发现其实dist[1]=4,dist[2]=2;先取1,再取2。

令人难受接受的是不是我们选取边的方式错了,而是算法本身就有漏洞!

因为上次dijkstra正确性证明时的dist[i]最小,则其则不存在其他店更新i的想法是错的!

这就需要我们寻找一个新的算法

就是bellman了

在这个算法中,我们暴力的把每条边都更新一次,更新|V|-1次,而且如果第|V|次还可以更新的话,就存在负权环了!

百度百科:

描述性证明

首先指出,图的任意一条最短路径既不能包含负权回路,也不会包含正权回路,因此它最多包含|v|-1条边。

其次,从源点s可达的所有顶点如果 存在最短路径,则这些最短路径构成一个以s为根的最短路径树。Bellman-Ford算法的迭代松弛操作,实际上就是按每个点实际的最短路径[虽然我们还不知道,但它一定存在]的层次,逐层生成这棵最短路径树的过程。

注意,每一次遍历,都可以从前一次遍历的基础上,找到此次遍历的部分点的单源最短路径。如:这是第i次遍历,那么,通过数学归纳法,若前面单源最短路径层次为1~(i-1)的点全部已经得到,而单源最短路径层次为i的点,必定可由单源最短路径层次为i-1的点集得到,从而在下一次遍历中充当前一次的点集,如此往复迭代,[v]-1次后,若无负权回路,则我们已经达到了所需的目的--得到每个点的单源最短路径。[注意:这棵树的每一次更新,可以将其中的某一个子树接到另一个点下]

反之,可证,若存在负权回路,第[v]次遍历一定存在更新,因为负权回路的环中,必定存在一个“断点”,可用数学手段证明。

最后,我们在第[v]次更新中若没有新的松弛,则输出结果,若依然存在松弛,则输出‘CAN‘T‘表示无解。同时,我们还可以通过“断点”找到负权回路。

所以总的时间复杂度为O(n*m),不算优,但可以优化到SPFA,具高效(貌似还是中国人发明的)

另外,运用bellman-Ford算法还可以解决差分约束图的问题

下一篇文章讨论。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#define INF 100000
const int N=500005;
struct note{
    int u,v,c;
}Edge[N];
int dist[N];
using namespace std;
int main()
{
    int n,m,s;
    scanf("%d %d %d",&n,&m,&s);
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d %d",&Edge[i].u,&Edge[i].v,&Edge[i].c);
    }
    for(int i=1;i<=n;i++)
    dist[i]=INF;
    dist[s]=0;
    for(int i=1;i<n;i++)
    {
        bool flag=1;
        for(int j=1;j<=m;j++)
        if(dist[Edge[j].u]+Edge[j].c<dist[Edge[j].v])
        dist[Edge[j].v]=dist[Edge[j].u]+Edge[j].c,flag=0;
        if (flag) break;
    }
    cout<<dist[1];
    for(int i=2;i<=n;i++)
    printf(" %d",dist[i]);
    cout<<endl;
}
//若有错误请大佬更正
时间: 2024-07-31 14:33:44

图论-Bellman-Ford的相关文章

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)初始化:将除源点外的所有顶点

ACM/ICPC 之 Bellman Ford练习题(ZOJ1791(POJ1613))

这道题稍复杂一些,需要掌握字符串输入的处理+限制了可以行走的时间. ZOJ1791(POJ1613)-Cave Raider //限制行走时间的最短路 //POJ1613-ZOJ1791 //Time:16Ms Memory:324K #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; #define MAX 505 #d

poj 3259 Wormholes (BELLman—FOrd算法)(邻接矩阵表示)

http://poj.org/problem?id=3259 之前一开始 ,没做出来,搁置了好几天才看见bug所在.所以今天a掉了 ,把代码贴出来,这个使用邻接矩阵表示的 ,下一篇用邻接表可以提高效率. #include<iostream> #include<queue> #include<stdio.h> #include<string.h> using namespace std; const int INF=600; int G[INF][INF];

Bellman ford 最短路径算法

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" /> 下表记录S到每一个节点的距离: 第一次迭代, S->A = 4 ,由于S->A眼下为INF.因此更新MIN(S->A)为4 S->B = 6.由于S->B眼下为INF.因此更新MIN(S->B)为6 S->C

最短路径——Bellman Ford算法(C++)

源代码: #include<cstdio>#include<cstring>int m(1),n,k,i[1001],x[1001],y[1001],f[1001];int main(){ scanf("%d%d",&n,&k); for (int a=1;a<=n;a++) for (int b=1;b<=n;b++) { scanf("%d",&i[m]); if (i[m]!=-1) { x[m]=a

poj3259 bellman——ford Wormholes解绝负权问题

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 35103   Accepted: 12805 Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way p

PKU 3169 Layout(差分约束系统+Bellman Ford)

题目大意:原题链接 当排队等候喂食时,奶牛喜欢和它们的朋友站得靠近些.FJ有N(2<=N<=1000)头奶牛,编号从1到N,沿一条直线站着等候喂食.奶牛排在队伍中的顺序和它们的编号是相同的.因为奶牛相当苗条,所以可能有两头或者更多奶牛站在同一位置上(即间距可能为0).即是说,如果我们想象奶牛是站在一条数轴上的话,允许有两头或更多奶牛拥有相同的横坐标. 一些奶牛相互间存有好感,它们希望两者之间的距离不超过一个给定的数L.另一方面,一些奶牛相互间非常反感,它们希望两者间的距离不小于一个给定的数D.