单源最小路径BellMan Ford算法

Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法。

输入:带权图

输出:从第0个点到其他点的最短路径值

Bellman-Ford 算法描述:

  1. 创建源顶点 v 到图中所有顶点的距离的集合 distSet,为图中的所有顶点指定一个距离值,初始均为 Infinite,源顶点距离为 0;
  2. 计算最短路径,执行 V – 1 次遍历;
    • 对于图中的每条边:如果起点 u 的距离 d 加上边的权值 w 小于终点 v 的距离 d,则更新终点 v 的距离值 d;
  3. 检测图中是否有负权边形成了环,遍历图中的所有边,计算 u 至 v 的距离,如果对于 v 存在更小的距离,则说明存在环

源码如下:

/*
  带权值图的一种表示方法:顶点与和向边数组
 */
public class DigraphVEW {
    String[] vertex;//所有顶点的数组,存放顶点的名字
    int verNum;//顶点个数
    Edge[] edgds;//所有带权边的数组

    public DigraphVEW(String[] vertex,  Edge[] edgds) {
        this.vertex = vertex;
        this.verNum = vertex.length;
        this.edgds = edgds;
    }

    public String[] getVertex() {
        return vertex;
    }

    public void setVertex(String[] vertex) {
        this.vertex = vertex;
    }

    public int getVerNum() {
        return verNum;
    }

    public Edge[] getEdgds() {
        return edgds;
    }

    public void setEdgds(Edge[] edgds) {
        this.edgds = edgds;
    }

    public static class Edge{
        int start;
        int end;
        int weight;

        public Edge(int start, int end, int weight) {
            this.start = start;
            this.end = end;
            this.weight = weight;
        }

        public int getStart() {
            return start;
        }

        public void setStart(int start) {
            this.start = start;
        }

        public int getEnd() {
            return end;
        }

        public void setEnd(int end) {
            this.end = end;
        }

        public int getWeight() {
            return weight;
        }

        public void setWeight(int weight) {
            this.weight = weight;
        }
    }
}
import java.util.Arrays;
/*
   单源最小路径算法,给出从一个点到其他所有点的最小路径
 */
public class BellMan {
    int[] minPaths; //记录从源点到所有其他点的最短路径
    DigraphVEW di;  //带权值的图
    int INF= 65535; //带表正无穷

    /*
    初始化
     */
    public BellMan(DigraphVEW di) {
        this.minPaths = new int[di.getVerNum()];
        this.di = di;
        Arrays.fill(minPaths,INF);
        minPaths[0] = 0;
    }

    public boolean bellManMinPath(){
        //如有n个顶点,最大遍历n-1次
        boolean isFinished = true;  //标识是否完成松驰,如果某次迭代后,所有点最小路径数据没变,则认为完成了。
        for (int i = 1; i < di.getVerNum(); i++) {
            for (DigraphVEW.Edge edge: di.getEdgds()) {
                if (edge.weight + minPaths[edge.start] < minPaths[edge.end]) {
                    minPaths[edge.end] = edge.weight + minPaths[edge.start];
                    isFinished = false;
                }
            }
            if (isFinished) {
                break;
            }
        }

        for (DigraphVEW.Edge edge: di.getEdgds()) {
            if (edge.weight + minPaths[edge.start] < minPaths[edge.end]) {
                return false;
            }
        }
        return true;
    }

    public int[] getMinPaths() {
        return minPaths;
    }
}

测试代码如下:针对以下两种情况

《单源最小路径BellMan Ford算法》

    @Test
    public void bellManMinPath() {
        String[] vertexs = new String[]{"A","B","C","D"};
        DigraphVEW.Edge[] edges = new DigraphVEW.Edge[]{
                new DigraphVEW.Edge(0,1,1),
                new DigraphVEW.Edge(0,2,2),
                new DigraphVEW.Edge(1,2,2),
                new DigraphVEW.Edge(1,3,6),
                new DigraphVEW.Edge(2,3,3)
        };
        DigraphVEW di = new DigraphVEW(vertexs,edges);

        BellMan bellMan= new BellMan(di);
        boolean result  = bellMan.bellManMinPath();
        assertEquals(true ,result);
        assertArrayEquals(new int[]{0,1,2,5},bellMan.getMinPaths());
    }

    @Test
    public void bellManMinPathFailed() {
        String[] vertexs = new String[]{"A","B","C","D"};
        DigraphVEW.Edge[] edges = new DigraphVEW.Edge[]{
                new DigraphVEW.Edge(0,1,1),
                new DigraphVEW.Edge(0,2,2),
                new DigraphVEW.Edge(1,2,2),
                new DigraphVEW.Edge(1,3,6),
                new DigraphVEW.Edge(2,3,3),
                new DigraphVEW.Edge(2,0,-5),
        };
        DigraphVEW di = new DigraphVEW(vertexs,edges);

        BellMan bellMan= new BellMan(di);
        boolean result  = bellMan.bellManMinPath();
        assertEquals(false ,result);
    }

 

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/tony820418/article/details/84861475
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞