Bellman-Ford Algorithm
Dijkstra算法虽然好,但是它不能解决带负权边,Floyd-Warshall虽然简单但时间复杂度高,
而Bellman-Ford 就是那个perfect。
核心代码:
for (int k=1; k<=n-1; k++)
for (int i=1; i<=m; i++)
if(dis[v[i]]>dis[u[i]]+w[i])
dis[v[i]]=dis[u[i]]+w[i];
上面的代码中,外循环一共循环了n-1次(n为顶点的个数),内循环循环了m次(m为边的个数),即枚举每一条边。
dis数组的作用与Dijkstra算法一样,是用来记录原点到其余各个顶点的最短路径。
u,v,和w三个数组是用来记录边的信息。
例如第i条边存储在u[i],v[i],w[i]中,表示从顶点u[i]到顶点v[i]这条边(u[i]->v[i])权值为w[i]。
if(dis[v[i]]>dis[u[i]]+w[i])
dis[v[i]]=dis[u[i]]+w[i];
上面这两行代码的意思是:看能否通过u[i]->v[i](权值为w[i])这条边,
使得1号顶点到v[i]号顶点的距离变短。
即1号顶点到u[[i]号顶点的距离(dis[u[i]])加上u[i]->v[i]这条边
(权值为w[i])的值是否比原先1号顶点到v[i]号顶点的距离(dis[v[i]])要小。
这一点其实与Dijkstra的“松弛”操作一样的。
只不过现在要把每条边都松弛一遍。
总结:最短路径上最多有n-1条边,因此Bellman-Ford算法最多有n-1个阶段,
在每个阶段我们都要对所边进行松弛操作,
所以就会有些已经求得最短路径,此后这些顶点的最短路的值就会一直不变了。
若在n-1之前所有的顶点都有了最短路的值就可跳出循环了,从而得到优化。
若已经过n-1个阶段,顶点的值还有变,则说明带有负权的回路