Bellman-Ford算法
来源:互联网 发布:mysql 保持数据一致性 编辑:程序博客网 时间:2024/04/29 17:24
Bellman-ford算法是求含负权图的单源最短路径算法,效率很低,但代码很容易写。即进行持续地松弛(原文是这么写的,为什么要叫松弛,争议很大),每次松弛把每条边都更新一下,若n-1次松弛后还能更新,则说明图中有负环,无法得出结果,否则就成功完成。Bellman-ford算法有一个小优化:每次松弛先设一个标识flag,初值为FALSE,若有边更新则赋值为TRUE,最终如果还是FALSE则直接成功退出。Bellman-ford算法浪费了许多时间做没有必要的松弛,而SPFA算法用队列进行了优化,效果十分显著,高效难以想象。SPFA还有SLF,LLL,滚动数组等优化。
Bellman-Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题。对于给定的带权(有向或无向)图 G=(V,E),其源点为s,加权函数 w是 边集 E 的映射。对图G运行Bellman-Ford算法的结果是一个布尔值,表明图中是否存在着一个从源点s可达的负权回路。若不存在这样的回路,算法将给出从源点s到 图G的任意顶点v的最短路径d[v]。
package com.gloomy.graph;import java.util.ArrayDeque;import java.util.ArrayList;import java.util.List;import java.util.Queue;/** * 处理存在负边值的最短路径算法 Bellman-Ford算法优化或的SPFA算法 * (无负值圈存在) * * * @author 过路的守望 * */public class WeightedNegative { public static void main(String[] args) { Vertex A = new Vertex("A"); Vertex B = new Vertex("B"); Vertex C = new Vertex("C"); Vertex D = new Vertex("D"); Vertex E = new Vertex("E"); Vertex F = new Vertex("F"); Vertex G = new Vertex("G"); A.getAdjacentList().add(B); A.getAdjacentList().add(D); A.getAdjacentEdgesMap().put(B, 2); A.getAdjacentEdgesMap().put(D, 1); B.getAdjacentList().add(E); B.getAdjacentEdgesMap().put(E, -11); C.getAdjacentList().add(A); C.getAdjacentEdgesMap().put(A, 4); C.getAdjacentList().add(F); C.getAdjacentEdgesMap().put(F, 2); D.getAdjacentList().add(C); D.getAdjacentEdgesMap().put(C, 5); D.getAdjacentList().add(F); D.getAdjacentEdgesMap().put(F, 6); D.getAdjacentList().add(G); D.getAdjacentEdgesMap().put(G, 2); E.getAdjacentList().add(G); E.getAdjacentEdgesMap().put(G, 6); E.getAdjacentList().add(D); E.getAdjacentEdgesMap().put(D, 1); G.getAdjacentList().add(F); G.getAdjacentEdgesMap().put(F, 1); List<Vertex> vertexs = new ArrayList<Vertex>(); vertexs.add(A); vertexs.add(B); vertexs.add(C); vertexs.add(D); vertexs.add(E); vertexs.add(F); vertexs.add(G); WeightedNegative weightedNegative = new WeightedNegative(); weightedNegative.weightedNegative(A, vertexs); } /** * 对算法进行优化,即每遍处理只对特定顶点出发的边做松弛操作。可以将发生变化的顶点的记录下来,在下一遍处理时对一这些顶点为源点的边做松弛操作。 * 我们使用队列结构来存储这些顶点 * * @param s * @param vertexs */ public void weightedNegative(Vertex s, List<Vertex> vertexs) { Queue<Vertex> queue = new ArrayDeque<Vertex>(); /* * 将起始顶点的路径长度置为0,加入队列中 */ s.setDist(0); queue.offer(s); Vertex curVertex = null; /* * 一直循环到队列为空退出 */ while (!queue.isEmpty()) { curVertex = queue.poll(); for (Vertex vertex : curVertex.getAdjacentList()) { /* * 更新起始顶点到当前顶点的路径长度 */ if (vertex.getDist() > curVertex.getDist() + curVertex.getAdjacentEdgesMap().get(vertex)) { vertex.setDist(curVertex.getDist() + curVertex.getAdjacentEdgesMap().get(vertex)); vertex.setPreVertex(curVertex); /* * 算法每遍处理对于各条边都进行检查将是很大的浪费,因为有大量的边并不会导致有效的松弛。事实上, * 唯一可能导致调整的边仅为某些特定顶点出发的边:这些顶点的值在上一遍处理中发生了变化。 */ if (!queue.contains(vertex)) { queue.offer(vertex); } } } } for (Vertex vertex5 : vertexs) { printPath(vertex5, vertexs.get(0)); System.out.println(); } } private void printPath(Vertex vertex, Vertex source) { if (vertex.getPreVertex() != null) { printPath(vertex.getPreVertex(), source); System.out.print(" " + "to" + " "); } System.out.print(vertex.getLabel()); }}
0 0
- Bellman-Ford&SPFA算法
- Bellman-ford算法实现
- Bellman-Ford 算法详解
- Bellman-Ford算法
- Bellman-Ford算法
- Bellman-Ford路由算法
- Bellman-Ford算法分析
- bellman ford算法
- Bellman-Ford算法
- Bellman-Ford算法总结
- Bellman-ford算法
- bellman-ford算法
- bellman-ford 算法
- Bellman-Ford算法
- Bellman-Ford算法
- bellman ford 算法
- Bellman-Ford 算法
- Bellman-Ford算法
- 函数调用堆栈
- Fresco的使用
- R笔记
- Manacher算法
- Spark 基础 —— RDD(二)
- Bellman-Ford算法
- hive启动出现权限错误 /tmp/hive on HDFS should be writable.
- Educational Codeforces Round 12 E. Beautiful Subarrays
- 无题
- Masonry适配——(3)UILable如何设置多行显示
- Android SD卡简单的文件读写操作
- spring @service @comment 原理
- 设计模式——策略对象
- SNAP--a scala of graph