首先,三者都是用来求最短路,但是思想和复杂度不相同。
bellman-ford 和spfa的区别
1.Bellman-ford算法中,循环n次,每次遍历m条边,每次遍历的时候,把入度的点的距离更新成最小。
然而,这样就循环遍历了很多用不到的边。比如第一次遍历,只有第一个点的临边是有效的。
2.因此,spfa算法中,采用邻接表的方式,只用到有效的点(更新了临边的点),直到每个点都是最短距离为止。采用队列优化的方式存储每次更新了的点,每条边最多遍历一次。如果存在负权回路,从起点1出发,回到1距离会变小, 会一直在三个点中循环。
Question:Question: 不用队列,遍历所有的点可以吗?
Ans:Ans:似乎不行,因为是更新了点之后,这个点的临边才可以用,如果没有更新到循环的点,那么循环的点也是不可用的。
spfa和dijkstra的区别:
st用来检验队列中是否有重复的点
spfa从队列中使用了当前的点,会把该点pop掉,状态数组st[i] = false(说明堆中不存在了) ,更新临边之后,把临边放入队列中, 并且设置状态数组为true,表示放入队列中 。如果当前的点距离变小,可能会再次进入队列,因此可以检验负环:
每次更新可以记录一次,如果记录的次数 > n,代表存在负环(环一定是负的,因为只有负环才会不断循环下去)。
st是一个集合,不是检验队列中的点。
dijkstra使用当前点更新临边之后,把该点加入到一个集合中,使用该点更新临边,并把临边节点和距离起点的距离置入堆中(不设置状态数组)。下一次从堆中取最小值,并把对应的节点放入集合中,继续更新临边节点,直到所有的点都存入集合中。因此dijkstra不判断负环。
从上述描述中能看出,dijkstra存放节点的堆,具有单调性,而spfa的队列不需要具有单调性。
作者:AnrolsP
链接:https://www.acwing.com/solution/content/21057/