单源最短路之Bellman-Ford算法

上次讲了图的储存,现在,我们就正式开始单源最短路的学习吧。

ffdcda60bb0c48b38d699ee231d74e46.png

 

 

7 11 5 4
2 4 2
1 4 3
7 2 2
3 4 3
5 7 5
7 3 3
6 1 1
6 3 4
2 4 3
5 6 3
7 2 1

还是来看这个图,目前我们已知的是这个图的各个边的情况以及它们的值,那么,如何求最短路呢?

Bellman-Ford算法通过从起点开始不断更新所有路径的最短距离,来实现最短路的求解。

下面看示例图解释(这里我们用一个数组d来存最短路径)(为了方便理解,我决定编个小故事):

很久很久以前,一个二次元世界上有七个大陆,每个大陆都不知道其他大陆的存在。

后来,一个从未来穿越过来的人来到了5号大陆,告诉那里的最有智慧的人其他六个大陆的存在。

然后使用了魔法,在七个大陆中随即建造了11条路。

这个未来人告诉五号大陆中最有智慧的人说:

“我想要前往四号大陆,你能帮我找到前往四号大陆的最短路径吗?我将非常感谢你。”

“实践是检验真理的唯一标准,所以,我应该去实践!”于是,五号大陆的智者出发了,并制作了图表来方便自己记录,毕竟,好记性不如烂笔头。

d: 1  2  3  4  5  6  7
    B  B  B  B  0  B  B

这里的B为INF(INF我们设置为一个很大的数,例如0x3f3f3f),因为智者并不知道五号大陆和其他大陆之间的距离,不过看上去很远,因为他只能看到海。

由于我们要求5到4的最短路,所以,这里5为起点,自己到自己的最短距离是0。于是智者将5的位置标为0。

接下来,未来人依靠超能力(别问为什么有超能力)告诉智者他建造的路的标号,但是没有告诉他路的长度。

于是,开始从上往下看有关5号大陆和其他大陆联通的情况。

 

5 7

很快,智者找到了这个,于是他决定先测量5号大陆和7号大陆的距离。

最后,结果为5。

于是,智者在自己制作的图表上记下了自己充满智慧的一笔。

d  1 2 3 4 5 6 7
   B B B B 0 B 5

此时,按理来说,智者应该开始看和7有关的联通大陆,但是未来人觉得这样太慢了,隔空传音告诉他,他将拥有分身,每个大陆都会有一个分身。

所以,现在,只要和5与7有关的都可以去测量了(由于分身来源于本体,所以,一次要么本体移动,要么其中一个分身移动。

比如,接下来智者很快就看到了

7 3

于是,不用我说,智者测量为3,接下来,图表为这样。

d 1 2 3 4 5 6 7
  B B 8 B 0 B 5

由于未来人需要的是5到4的距离,所以这里3为5到7到3,而不是7到3的距离,所以为8。

最后,经过智者不懈的努力,图表变成了这个样子:

d 1 2 3 4 5 6 7
  4 6 7 7 0 3 5

至此,智者很满意和骄傲自豪的对未来人说:“是7!”

未来人一脸欣慰的对智者竖起大拇指,说道:“很好!”

随后,智者的图表传给后代,最后来到了Bellman-Ford的手中(bushi

下面上代码:

const int INF= 0x3f3f3f;//设置一个INF为很大的值 
int d[6210];//d是最短路 
void short_path(int k)
{
	for(int i=1;i<=n;i++)d[i]=INF;//设置起点到每个点的距离为B,很大
	d[k]=0;//起点到起点距离为0
	while(true){
		bool update=false;//如果不再更新,就说明所以的路况已经探查清楚,并且都已经是最短路了。
		for(int i=1;i<=m;i++)
		{
			edge e=es[i];
			if(d[e.from ]!=INF&&d[e.to ]>d[e.from]+e.cost)//如果起点到终点的距离小于原先记录的,则更新值。
			{
				d[e.to]=d[e.from]+e.cost;//更新原先记录的。
				update=true;//更新,说明又可能还要继续更新。
			}
			if(d[e.to]!=INF&&d[e.from ]>d[e.to]+e.cost)//这里不是单向图,所以终点到起点的距离也要更新记录。
			{
				d[e.from]=d[e.to]+e.cost;
				update=true;
			}
		}
		if(!update)break;//如果不再更新就结束循环。
	}
	
	
	
}

判断负环的代码这里先不介绍了,等以后再做介绍OvO

下面让我们打上这个,去LuoguAC题目吧!(P1339)

short_path(s);
	cout<<d[t];

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值