通用的Bellman-Ford:
特点:能处理存在负权边的情况,并能判断是否存在负权回路。可以用在差分约束系统问题的求解,有解情况下最短路径是一组可行解。效率低,O(VE)。
过程:做 顶点数(V) - 1 次对所有边的松弛操作,也可以加一个flag检查到没有需要松弛的时候便结束,快一点。再检查一遍是否有边还能做松弛操作(把松弛操作比较部分反过来做判断条件),若能则说明有负权回路。
注:负权回路很多时候能代表存在一些不合理的性质(让人可以钻空子的bug),比如交易系统可以交易一圈(即最终交易回初始物品)之后得到多的钱poj1860,不合理的虫洞旅行见到旅行前的自己(在科幻片中类似场景层出不穷)poj3259,这种情况就可以用该算法来检测。也就是说,该算法不仅可以用来求存在负权边的最短路,还可以用来检测是否存在负权回路。
dag(有向无回图)(directed acyclic graphs):
特点:对dag图能做,能处理负权边,效率高,O(V+E)。可用于 求PERT图(program evaluation and review technique chart,程序评价和审查技术图)中的关键路径(关键路径指通过dag的一条最长路径),由于PERT图反应工作的依赖关系,必然是dag。
过程:拓扑排序,按序对边做一次松弛操作。
Dijkstra:
特点:不能处理负权边,效率较高(效率取决于优先队列的实现方式,二叉堆实现时为O((V+E)lgV))。
过程:类似BFS,不过把普通的队列换成了优先队列。
DIJIKSTRA(G,w,s)
//initial
initialize_single_source(G,s)
//bfs
S <- empty //work as color[]
Q <- V[G]
while Q != empty
do u <- extract_min(Q)
S <- S + {u}
for each v from Adj[u]
do RELAX(u,v,w)