2

我会实现Edmond Karp 算法,但它似乎不正确而且我没有得到正确的流程,请考虑以下图表和从 4 到 8 的流程:

在此处输入图像描述

在此处输入图像描述

算法运行如下:

先找4→1→8,再找4→5→8,再找4→1→6→8

而且我认为第三条路径是错误的,因为使用这条路径我们不能使用 6→8 的流(因为它使用过),实际上我们不能使用 4→5→6→8 的流。

事实上,如果我们选择 4→5→6→8,然后是 4→1→3→7→8,然后是 4→1→3→7→8,我们可以获得更好的流量(40)。

我从 wiki 示例代码中实现了算法。我认为我们不能使用任何有效的路径,实际上这种贪婪的选择是错误的。

我错了吗?

代码如下(c#中阈值为0,不影响算法):

   public decimal EdmondKarps(decimal[][] capacities/*Capacity matrix*/,
                    List<int>[] neighbors/*Neighbour lists*/,
                    int s /*source*/,
                    int t/*sink*/,
                    decimal threshold,
                    out decimal[][] flowMatrix
                    /*flowMatrix (A matrix giving a legal flowMatrix with the maximum value)*/
                    )
    {
        THRESHOLD = threshold;
        int n = capacities.Length;
        decimal flow = 0m; // (Initial flowMatrix is zero)
        flowMatrix = new decimal[n][]; //array(1..n, 1..n) (Residual capacity from u to v is capacities[u,v] - flowMatrix[u,v])
        for (int i = 0; i < n; i++)
        {
            flowMatrix[i] = new decimal[n];
        }

        while (true)
        {
            var path = new int[n];
            var pathCapacity = BreadthFirstSearch(capacities, neighbors, s, t, flowMatrix, out path);
            if (pathCapacity <= threshold)
                break;
            flow += pathCapacity;

            //(Backtrack search, and update flowMatrix)
            var v = t;
            while (v != s)
            {
                var u = path[v];
                flowMatrix[u][v] = flowMatrix[u][v] + pathCapacity;
                flowMatrix[v][u] = flowMatrix[v][u] - pathCapacity;
                v = u;
            }
        }
        return flow;
    }

    private decimal BreadthFirstSearch(decimal[][] capacities, List<int>[] neighbors, int s, int t, decimal[][] flowMatrix, out int[] path)
    {
        var n = capacities.Length;
        path = Enumerable.Range(0, n).Select(x => -1).ToArray();//array(1..n)
        path[s] = -2;
        var pathFlow = new decimal[n];
        pathFlow[s] = Decimal.MaxValue; // INFINT
        var Q = new Queue<int>(); // Q is exactly Queue :)
        Q.Enqueue(s);
        while (Q.Count > 0)
        {
            var u = Q.Dequeue();
            for (int i = 0; i < neighbors[u].Count; i++)
            {
                var v = neighbors[u][i];
                //(If there is available capacity, and v is not seen before in search)
                if (capacities[u][v] - flowMatrix[u][v] > THRESHOLD && path[v] == -1)
                {
                    // save path:
                    path[v] = u;
                    pathFlow[v] = Math.Min(pathFlow[u], capacities[u][v] - flowMatrix[u][v]);
                    if (v != t)
                        Q.Enqueue(v);
                    else
                        return pathFlow[t];
                }
            }
        }
        return 0;
    }
4

1 回答 1

2

选择路径的方式并不重要。

您必须以与路径容量相反的顺序添加路径的边缘,并通过该值减少路径边缘的容量。

事实上,这个解决方案有效:

while there is a path with positive capacity from source to sink{
    find any path with positive capacity from source to sink, named P with capacity C.
    add C to maximum_flow_value.
    reduce C from capacity of edges of P.
    add C to capacity of edges of reverse_P.
}

最后maximum-flow的值是C循环中s的总和。

如果您想查看您制作的最大流量中的边流,您可以将初始图保留在某处,边 e 中的流将是 original_capacity_e - current_capacity_e。

于 2012-02-25T16:29:27.210 回答