首先明确,不是这个算法规定了一定要n-1次循环
而是这个算法最坏的情况
下需要n-1次循环。
为什么?一说就懂
什么情况下最好?
这是我们的图: 很简单的一个图,四个节点,三个边(长度分别是:3 7 12)
1 --(3)---2--(7)---3--(12)--4
让你求出,从1出发的最短路径
1 .假如题目这样描述:
1 2 3
2 3 7
3 4 12
能理解吧? (起点,终点, 长度)
关键就在于我们从上到下按顺序
,把这三个边, 依次存进了 你的 edge[] 数组里面 ,对吧?
来看看Bellman算法的代码中,我们是咋操作的
-
先把dis 数组,起点处设置为 0 , 其它点设置为INF, dis[1] = 0 , 其他的dis[] =INF
-
对于每一次循环, 算法要求我们,更新 m 条边。
for(i=0;i<N-1;i++){
for(j=0;j<G;j++){
int u=e[j].u,v=e[j].v;
if(d[u]!=INF&&d[u]+w[u][v]<d[v]) d[v]=d[u]+w[u][v];
}
}
我们来动手做一下
第一次循环。。。。。。
dis[1]=0
dis[2] =3 ,因为 dis[1] + map[1][2] < dis[2],也就是 3 + 0 <INF
dis[3] = 10 ,同理
dis[4] = 22 , 同理
第二次循环。。。。。。。
dis[1] =0
dis[2] = 3
dis[3] =10
dis[4] = 22 ,我靠,啥都没做,
第三次循环。。。。。。
也啥都没做
发现了吗? 我们仅仅一次循环就出结果了,谁还费那劲要做n-1 次循环????
但是,如果是这种呢?
2 .假如题目这样描述:
3 4 12
2 3 7
1 2 3
我们再动手操作一次
第一次循环。。。。。。
dis[4]=inf
dis[3]=inf ,
dis[2] =3 ,
dis[1]= 0 ,
第二次循环。。。。。。。
dis[4]=inf
dis[3]= 10 ,
dis[2] =3 ,
dis[1]= 0 ,
第三次循环。。。。。。
dis[4]=22
dis[3]=10,
dis[2] =3 ,
dis[1]= 0 ,
我们必须,做n-1次循环,才能出结果
原因就是:
我们按顺序存入边,
但是这个顺序有时候很好,(我们第一次循环就是从前往后循环),导致第一次循环就更新了 所有的节点
这个顺序有时候很差(我们每次都是从路径的后面向前面更新),导致每次循环仅仅更新一个
所以,我们为了应对最差情况,不得不更新n-1次。
现在你懂了为啥循环中间有个剪枝了吧,就是担心情况太好, 导致后面的循环白白浪费时间,早点剪枝跳出循环。