コード例 #1
0
        // is there an augmenting path?
        // if so, upon termination edgeTo[] will contain a parent-link representation of such a path
        // this implementation finds a shortest augmenting path (fewest number of edges),
        // which performs well both in theory and in practice
        private bool hasAugmentingPath(FlowNetwork G, int s, int t)
        {
            edgeTo = new FlowEdge[G.V];
            marked = new bool[G.V];

            // breadth-first search
            LinkedQueue <int> queue = new LinkedQueue <int>();

            queue.Enqueue(s);
            marked[s] = true;
            while (!queue.IsEmpty && !marked[t])
            {
                int v = queue.Dequeue();

                foreach (FlowEdge e in G.Adj(v))
                {
                    int w = e.Other(v);

                    // if residual capacity from v to w
                    if (e.ResidualCapacityTo(w) > 0)
                    {
                        if (!marked[w])
                        {
                            edgeTo[w] = e;
                            marked[w] = true;
                            queue.Enqueue(w);
                        }
                    }
                }
            }
            // is there an augmenting path?
            return(marked[t]);
        }
コード例 #2
0
        public static void MainTest(string[] args)
        {
            TextInput   input = new TextInput(args[0]);
            FlowNetwork G     = new FlowNetwork(input);

            Console.WriteLine(G);
        }
コード例 #3
0
        // return excess flow at vertex v
        private double excess(FlowNetwork G, int v)
        {
            double excess = 0.0;

            foreach (FlowEdge e in G.Adj(v))
            {
                if (v == e.From)
                {
                    excess -= e.Flow;
                }
                else
                {
                    excess += e.Flow;
                }
            }
            return(excess);
        }
コード例 #4
0
        // check optimality conditions
        private bool check(FlowNetwork G, int s, int t)
        {
            // check that flow is feasible
            if (!isFeasible(G, s, t))
            {
                Console.Error.WriteLine("Flow is infeasible");
                return(false);
            }

            // check that s is on the source side of min cut and that t is not on source side
            if (!InCut(s))
            {
                Console.Error.WriteLine("source " + s + " is not on source side of min cut");
                return(false);
            }
            if (InCut(t))
            {
                Console.Error.WriteLine("sink " + t + " is on source side of min cut");
                return(false);
            }

            // check that value of min cut = value of max flow
            double mincutValue = 0.0;

            for (int v = 0; v < G.V; v++)
            {
                foreach (FlowEdge e in G.Adj(v))
                {
                    if ((v == e.From) && InCut(e.From) && !InCut(e.To))
                    {
                        mincutValue += e.Capacity;
                    }
                }
            }

            if (Math.Abs(mincutValue - value) > FloatingPointEpsilon)
            {
                Console.Error.WriteLine("Max flow value = " + value + ", min cut value = " + mincutValue);
                return(false);
            }
            return(true);
        }
コード例 #5
0
        // return excess flow at vertex v
        private bool isFeasible(FlowNetwork G, int s, int t)
        {
            // check that capacity constraints are satisfied
            for (int v = 0; v < G.V; v++)
            {
                foreach (FlowEdge e in G.Adj(v))
                {
                    if (e.Flow < -FloatingPointEpsilon || e.Flow > e.Capacity + FloatingPointEpsilon)
                    {
                        Console.Error.WriteLine("Edge does not satisfy capacity constraints: " + e);
                        return(false);
                    }
                }
            }

            // check that net flow into a vertex equals zero, except at source and sink
            if (Math.Abs(value + excess(G, s)) > FloatingPointEpsilon)
            {
                Console.Error.WriteLine("Excess at source = " + excess(G, s));
                Console.Error.WriteLine("Max flow         = " + value);
                return(false);
            }
            if (Math.Abs(value - excess(G, t)) > FloatingPointEpsilon)
            {
                Console.Error.WriteLine("Excess at sink   = " + excess(G, t));
                Console.Error.WriteLine("Max flow         = " + value);
                return(false);
            }
            for (int v = 0; v < G.V; v++)
            {
                if (v == s || v == t)
                {
                    continue;
                }
                else if (Math.Abs(excess(G, v)) > FloatingPointEpsilon)
                {
                    Console.Error.WriteLine("Net flow out of " + v + " doesn't equal zero");
                    return(false);
                }
            }
            return(true);
        }
コード例 #6
0
        public static void MainTest(string[] args)
        {
            //create flow network with V vertices and E edges
            int         V = int.Parse(args[0]);
            int         E = int.Parse(args[1]);
            int         s = 0, t = V - 1;
            FlowNetwork G = new FlowNetwork(V, E);

            Console.WriteLine(G);

            // compute maximum flow and minimum cut
            FordFulkerson maxflow = new FordFulkerson(G, s, t);

            Console.WriteLine("Max flow from " + s + " to " + t);
            for (int v = 0; v < G.V; v++)
            {
                foreach (FlowEdge e in G.Adj(v))
                {
                    if ((v == e.From) && e.Flow > 0)
                    {
                        Console.WriteLine("   " + e);
                    }
                }
            }

            // print min-cut
            Console.Write("Min cut: ");
            for (int v = 0; v < G.V; v++)
            {
                if (maxflow.InCut(v))
                {
                    Console.Write(v + " ");
                }
            }
            Console.WriteLine();

            Console.WriteLine("Max flow value = " + maxflow.Value);
        }
コード例 #7
0
        private double value;      // current value of max flow

        /// <summary>
        /// Compute a maximum flow and minimum cut in the network <c>G</c>
        /// from vertex <c>s</c> to vertex <c>t</c>.</summary>
        /// <param name="G">the flow network</param>
        /// <param name="s">the source vertex</param>
        /// <param name="t">the sink vertex</param>
        /// <exception cref="IndexOutOfRangeException">unless 0 &lt;= s &lt; V</exception>
        /// <exception cref="IndexOutOfRangeException">unless 0 &lt;= t &lt; V</exception>
        /// <exception cref="ArgumentException">if s = t</exception>
        /// <exception cref="ArgumentException">if initial flow is infeasible</exception>
        ///
        public FordFulkerson(FlowNetwork G, int s, int t)
        {
            validate(s, G.V);
            validate(t, G.V);
            if (s == t)
            {
                throw new ArgumentException("Source equals sink");
            }
            if (!isFeasible(G, s, t))
            {
                throw new ArgumentException("Initial flow is infeasible");
            }

            // while there exists an augmenting path, use it
            value = excess(G, t);
            while (hasAugmentingPath(G, s, t))
            {
                // compute bottleneck capacity
                double bottle = double.PositiveInfinity;
                for (int v = t; v != s; v = edgeTo[v].Other(v))
                {
                    bottle = Math.Min(bottle, edgeTo[v].ResidualCapacityTo(v));
                }

                // augment flow
                for (int v = t; v != s; v = edgeTo[v].Other(v))
                {
                    edgeTo[v].AddResidualFlowTo(v, bottle);
                }

                value += bottle;
            }

            // check optimality conditions
            Debug.Assert(check(G, s, t));
        }