`
128kj
  • 浏览: 583984 次
  • 来自: ...
社区版块
存档分类
最新评论

图解Bellman-Ford算法

阅读更多
Bellman-Ford算法:
     为了能够求解边上带有负值的单源最短路径问题,Bellman(贝尔曼)和Ford(福特)提出了从源点逐次绕过其他顶点,以缩短到达终点的最短路径长度的方法。











    Bellman-ford算法是求解连通带权图中单源最短路径的一种算法,它允许图中存在权值为负的边。同时它还能够判断出图中是否存在一个权值之和为负的回路。如果存在的话,图中就不存在最短路径(因为,假设存在最短路径的话,那么我们只要将这条最短路径沿着权值为负的环路再绕一圈,那么这条最短路径的权值就会减少了,所以不存在最短的路径,因为路径的最小值为负无穷),如果不存在的话,那么求出源点到所有节点的最短路径。


     Bellman-Ford算法主要是针对有负权值的图。来判断该图中是否有负回路,或者存在最短路径的点。判断的思路,从源点出发,进行n - 1(n为顶点数)遍历,在每次的遍历过程中,对所有的边进行遍历判断,同样是利用松弛计算的思想,dis[v] > dis[u] + w(u, v)不断更新dis数组的值,直到循环结束。然后就是这个算法最精彩的地方了,再对所有的边进行一次遍历,看是否存在dis[v] > dis[u] + w(u, v)的边,若存在,则返回FALSE,说明图中存在负回路;若不存在,则返回TRUE,dis数组记录的就是每一个点到源点的最小值。


例:求如图中A点到各点的最短距离


  
/** 
 * 采用保存边的方式来存储图的的信息。 
 * p保存的是前驱节点,d保存的是源点到每一个点的最短距离。我们最后又做了一次判断,如果还有可以松弛 
 * 的边,那么可以保证的是图中有负权的环存在,这样的话就没有最短路径只说了,可以无限小。 
 *  
 * @author daijope 
 * 
 */  
public class BellmanFord {  
    private static final int m = 10000;  
    public static void main(String[] args) {  
          
        Adge a1 = new Adge(0, 1, -1);  
        Adge a2 = new Adge(0, 2, 4);  
        Adge a3 = new Adge(1, 2, 3);   
        Adge a4 = new Adge(3, 1, 1);  
        Adge a5 = new Adge(1, 3, 2);  
        Adge a6 = new Adge(3, 2, 5);  
        Adge a7 = new Adge(1, 4, 2);  
        Adge a8 = new Adge(4, 3, -3);  
        Adge[] as = new Adge[]{a1, a2, a3, a4, a5, a6, a7, a8};  
          
        int[] d = new int[5];  
        int[] p = new int[5];  
        d[0] = 0;  
        p[0] = 0;  
        for (int i = 1; i < d.length; i++) {  
            d[i] = m;  
            p[i] = -1;  
        }  
        bellman_Ford(as, d, p);  
          
        for (int i = 0; i < d.length; i++) {  
            System.out.println(d[i]);  
        }  
    }  
    private static void bellman_Ford(Adge[] as, int[] d, int[] p){  
        for(int i = 1; i < d.length; i++) {  
            for (int j = 0; j < as.length; j++) {  
                if (d[as[j].getV()] > d[as[j].getU()] + as[j].getW()) {  
                    d[as[j].getV()] = d[as[j].getU()] + as[j].getW();  
                    p[as[j].getV()] = as[j].getU();  
                }  
            }  
        }  
        for (int j = 0; j < as.length; j++) {  
            if (d[as[j].getV()] > d[as[j].getU()] + as[j].getW()) {  
                System.out.println("有负环");  
            }  
        }  
  
          
    }  
}  
class Adge {  
    private int u;  
    private int v;  
    private int w;  
      
    public Adge(int u, int v, int w) {  
        this.u = u;  
        this.v = v;  
        this.w = w;  
    }  
  
    public int getU() {  
        return u;  
    }  
  
    public void setU(int u) {  
        this.u = u;  
    }  
  
    public int getV() {  
        return v;  
    }  
  
    public void setV(int v) {  
        this.v = v;  
    }  
  
    public int getW() {  
        return w;  
    }  
  
    public void setW(int w) {  
        this.w = w;  
    }  
      
      
}  


运行:
C:\java>java   BellmanFord
0
-1
2
-2
1

下载源码
  • 大小: 38.8 KB
  • 大小: 25.2 KB
  • 大小: 11.2 KB
  • 大小: 7 KB
  • 大小: 36.9 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics