贝尔曼-福特-动态规划

183 阅读2分钟

贝尔曼-福特(Bellman-Ford)算法是一种用于解决图中单源最短路径问题的算法,可以处理带有负权边的情况,同时也能够检测负权环。这个算法以其在实际应用中的灵活性和鲁棒性而闻名,以下是它的基本原理和步骤:

1.初始化:首先,将源节点到自身的距离设置为0,将源节点到其他所有节点的距离初始化为正无穷大。同时,为每个节点设置一个前驱节点,用于最终路径还原。

2.松弛操作:进行|V| - 1轮松弛操作,其中|V|是图中节点的数量。在每一轮中,遍历图中的所有边,尝试通过当前节点来找到到其他节点的更短路径。如果找到了更短的路径,就更新距离和前驱节点的信息。

3.检测负权环:在第|V|轮松弛操作之后,如果仍然可以通过松弛操作减小某些节点的距离,那么说明图中存在负权环。这是贝尔曼-福特算法的一个独特之处,因为它可以检测到负权环的存在。

4.最短路径还原:一旦算法完成,你可以使用前驱节点信息来还原从源节点到其他节点的最短路径。

贝尔曼-福特算法的时间复杂度为O(|V| * |E|),其中|V|是节点数,|E|是边数。它适用于带有负权边的情况,而Dijkstra算法在这种情况下无法正常工作。然而,它可能不如Dijkstra算法在正权边较多的情况下高效,因为它需要进行多轮松弛操作。 这个算法在网络路由、图论、金融建模和其他领域都有广泛的应用,特别是当需要考虑负权边或负权环时。

public class BellmanFord {

    static class Edge {

        //起点
        int from;
        //终点
        int to;
        //权重
        int weight;

        public Edge(int from, int to, int weight) {
            this.from = from;
            this.to = to;
            this.weight = weight;
        }
    }

    public static void main(String[] args) {
        Edge e1 = new Edge(6, 5, 9);
        Edge e2 = new Edge(4, 5, 6);
        Edge e3 = new Edge(1, 6, 14);
        Edge e4 = new Edge(3, 6, 2);
        Edge e5 = new Edge(3, 4, 11);
        Edge e6 = new Edge(2, 4, 15);
        Edge e7 = new Edge(1, 3, 9);
        Edge e8 = new Edge(1, 2, 7);

        List<Edge> edges = new ArrayList<>();
        Collections.addAll(edges,e1,e2,e3,e4,e5,e6,e7,e8);

        int[] dp = new int[7];//一维数组,缓存结果

        //初始化
        dp[1] = 0;
        for (int i = 2; i < dp.length; i++) {
            dp[i] = Integer.MAX_VALUE;
        }

        print(dp);

        //6条边,最多循环5轮
        for (int i = 0; i < 5; i++) {
            for (Edge e : edges) {
                if (dp[e.from] != Integer.MAX_VALUE) {
                    dp[e.to] = Integer.min(dp[e.to], dp[e.from] + e.weight);
                }
            }
        }

        print(dp);
    }

    //打印数组内容
    static void print(int[] dp) {
        System.out.println(Arrays.stream(dp).mapToObj(i -> i == Integer.MAX_VALUE ? "@" : String.valueOf(i))
                .collect(Collectors.joining(",", "[", "]")));
    }

}