【问题标题】:Bellman-Ford algorithm correct & standard implementationBellman-Ford 算法正确&标准实现
【发布时间】:2019-07-14 20:27:59
【问题描述】:

我一直在尝试通过以下资源了解 Bellman-Ford 的正确实现:1 & 2

如果我们已经知道给定的加权有向图不包含循环(因此也没有负循环),那么是否遵循 Bellman-Ford 算法的正确实现?

int src = 0;
        int V = nodes.length; // 0 to n-1 nodes
        int E = edges.length;

        double[] distTo = new double[V];
        for (int i = 0; i < V; i++) {
            distTo[i] = Double.POSITIVE_INFINITY;
        }
        int[] edgeTo = new int[V];

        distTo[src] = 0.0;

        for (int i = 1; i < V - 1; i++) {

            double[] distToLocal = new double[V];
            for (int j = 0; j < V; j++) {
                distToLocal[j] = Double.POSITIVE_INFINITY;
            }

            for (int j = 0; j < E; j++) {

                int to = edges[i].to;
                int from = edges[i].from;
                int weight = edges[i].weight;

                if (distToLocal[to] > distTo[to] && distToLocal[to] > distTo[from] + weight) {
                    distToLocal[to] = distTo[from] + weight;
                    edgeTo[to] = from;
                }
              distToLocal[to] = Math.min(distToLocal[to],distTo[to]);

            }
            distTo = distToLocal;
        }

我在上述实现中遇到的第一个问题是,如果图中只有 2 个节点具有从源节点到目标节点的有向边,则需要修改第一个 for 循环以开始0 代替 1 如下:

for (int i = 0; i < V - 1; i++) {

如果我进行上述更改,它仍然是正确的实现吗?

实施方式的变化

如果不需要找到节点与src 的最短距离,其中 K 为 [0,V-1] 的最大 K 条边,那么以下变化似乎也能给出正确的结果。

int src = 0;
        int V = nodes.length; // 0 to n-1 nodes
        int E = edges.length;

        double[] distTo = new double[V];
        for (int i = 0; i < V; i++) {
            distTo[i] = Double.POSITIVE_INFINITY;
        }
        int[] edgeTo = new int[V];

        distTo[src] = 0.0;

        for (int i = 1; i < V - 1; i++) {

            /*double[] distToLocal = new double[V];
            for (int j = 0; j < V; j++) {
                distToLocal[j] = Double.POSITIVE_INFINITY;
            }*/

            for (int j = 0; j < E; j++) {

                int to = edges[i].to;
                int from = edges[i].from;
                int weight = edges[i].weight;

                if (distTo[to] > distTo[from] + weight) {
                    distTo[to] = distTo[from] + weight;
                    edgeTo[to] = from;
                }
            }
            //distTo = distToLocal;
        }

我想我理解为什么变体有效,但是我很好奇为什么资源 1 没有提到这一点。

实施这种变体有什么缺点吗?显然,该变体具有更好的内存要求。

注意:我知道当加权有向图中没有环时我可以使用拓扑排序 SPT 算法,但我试图理解 Bellman-Ford 的正确性。

【问题讨论】:

    标签: java graph-theory bellman-ford


    【解决方案1】:

    Bellman-Ford 算法指出,在每条边的 V-1 阶段松弛之后,将计算源到任何目的地之间的最小距离。在您的实现中,您运行每个阶段的 V-2 迭代。实际上,两个实现是相同的,您可以重用旧的距离数组。

    【讨论】:

    • 感谢您回答我的问题!在任何情况下,第一个实现优于第二个?我确定“最大 K 边”限制是需要第一次实现的场景。还有其他情况吗?
    猜你喜欢
    • 2015-08-27
    • 1970-01-01
    • 1970-01-01
    • 2015-05-04
    • 2020-03-23
    • 1970-01-01
    • 2015-07-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多