Bellman-Ford算法
解决的问题:
n个顶点,m条边,分别求出源点到其它各点的最短距离。
接下来就是m行边的数据
a b c
…
代表顶点a到顶点b距离为c
试用条件:
- 边权值可正可负。
- 可以是无向边或者有向边
- 图内不能有负权环(环内存在边值为负),因为求出的最短路不正确。
有正环暂时没发现求最短路有错误。 - 但该算法可检测是否存在负权环。
核心代码(4行):
不断利用m条边更新最短路
for(k=1;k<=n-1;k++)
for(i=1;i<=m;i++)
if(dis[v[i]]>dis[u[i]]+w[i])
dis[v[i]]=dis[u[i]]+w[i];
注解:
数组u,v,w分别存m条边的信息。
u[i],v[i],w[i]存的就是第 i 条边的信息。
dis[i]表示的是源点到i的最短距离。
为什么外层循环(n-1)次呢?
——因为任意两点的路径可以有多条,但不管是哪条路径,含边数最多为 n - 1 条,因此任意两点之间的最短路径最多包含 n - 1 边。
——假定:源点为1。
当 k = 1 时,表示从 1 号顶点 “ 最多经过一条边 ” 到达其余各顶点的最短路径长度。
当 k = 2 时,表示从1号顶点 “ 最多经过两条边 ” 到达其余各顶点的最短路径长度。
…
当 k = n - 1 时,表示从1号顶点 “ 最多经过 n - 1 条边 ”到达其余各顶点的最短路径长度。
——现在要对这两句话稍微变更一下。
无时无刻都在想着更新dis的值。
当 k = 1 时,数组dis存的是1号顶点一步之内可到达的最短路径。
当 k = 2 时,数组dis存的是1号顶点两步之内可到达的最短路径。因为在 k = 1 时,对dis数组有了更新,因此当k=2时就相当于在k=1时再走一步。
当k=3时…
注意:这里的一步并非只走一条边的意思,所以即使存在最短路是 n - 1 条边,往往也不用循环(n-1)次,算了,把自己搞迷了。
——有没有丝丝的熟悉感呢。
没错,就是广搜思想,层层向外扩展,是否已经知晓为啥最多进行 n - 1 轮了呢,因为总共n个顶点,任意两点之间的最短路径最多包含 n - 1 条边。
稍微优化一点点:
——添加一个标记,是否提前跳出。当发现一轮下来,所有dis都未更新,就可以结束循环了,因为已经实现全部源点到其它点最小了。
再优化之Bellman-Ford的队列优化(spfa)
写不下去了,上简单题:牛客例题1