/// <summary>
        /// This is the core part of the algorithm, "phase one."
        /// </summary>
        /// <returns></returns>
        private double MaximumPreflow()
        {
            workSinceLastUpdate = 0;

            while (maxActive >= minActive)                      // "main" loop
            {
                PreflowLayer layer = layers[maxActive];

                if (layer.ActiveVertices.Count == 0)
                {
                    --maxActive;
                }
                else
                {
                    IVertex u = layer.ActiveVertices[0];
                    RemoveFromActiveList(u);

                    Discharge(u);

                    if (workSinceLastUpdate * globalUpdateFrequency > nm)
                    {
                        GlobalDistanceUpdate();
                        workSinceLastUpdate = 0;
                    }
                }
            }

            return(excessFlow[sink]);
        }
        //=======================================================================
        // This function is called "push" in Goldberg's h_prf implementation,
        // but it is called "discharge" in the paper and in hi_pr.c.
        private void Discharge(IVertex u)
        {
            while (true)
            {
                int ai;
                for (ai = current[u]; ai < VisitedGraph.OutDegree(u); ai++)
                {
                    IEdge a = VisitedGraph.OutEdges(u)[ai];
                    if (IsResidualEdge(a))
                    {
                        IVertex v = a.Target;
                        if (IsAdmissible(u, v))
                        {
                            if (v != sink && excessFlow[v] == 0)
                            {
                                RemoveFromInactiveList(v);
                                AddToActiveList(v, layers[distances[v]]);
                            }
                            PushFlow(a);
                            if (excessFlow[u] == 0)
                            {
                                break;
                            }
                        }
                    }
                }

                PreflowLayer layer = layers[distances[u]];
                int          du    = distances[u];

                if (ai == VisitedGraph.OutDegree(u))                            // i must be relabeled
                {
                    RelabelDistance(u);
                    if (layer.ActiveVertices.Count == 0 &&
                        layer.InactiveVertices.Count == 0)
                    {
                        Gap(du);
                    }
                    if (distances[u] == n)
                    {
                        break;
                    }
                }
                else
                {                                                                               // i is no longer active
                    current[u] = ai;
                    AddToInactiveList(u, layer);
                    break;
                }
            }
        }
        private void Initialize()
        {
            int m = 0;
            n = VisitedGraph.VerticesCount;
            foreach (IVertex u in VisitedGraph.Vertices)
                m += VisitedGraph.OutDegree(u);
            // Don't count the reverse edges
            m /= 2;
            nm = alpha * n + m;

            excessFlow.Clear();
            current.Clear();
            distances.Clear();

            layers = new PreflowLayer[n];
            for (int i = 0; i < n; i++)
                layers[i] = new PreflowLayer();

            // Initialize flow to zero which means initializing
            // the residual capacity to equal the capacity.
            foreach (IVertex u in VisitedGraph.Vertices)
            {
                foreach (IEdge e in VisitedGraph.OutEdges(u))
                    this.ResidualCapacities[e] = this.Capacities[e];

                excessFlow[u] = 0;
                current[u] = 0;
            }

            bool overflowDetected = false;
            double testExcess = 0;

            foreach (IEdge a in VisitedGraph.OutEdges(src))
            {
                if (a.Target != src)
                    testExcess += this.ResidualCapacities[a];
            }

            if (testExcess >= double.MaxValue || double.IsPositiveInfinity(testExcess))
                overflowDetected = true;

            if (overflowDetected)
            {
                excessFlow[src] = double.MaxValue;
            }
            else
            {
                excessFlow[src] = 0;
                foreach (IEdge a in this.VisitedGraph.OutEdges(src))
                {
                    if (a.Target != src)
                    {
                        double delta = this.ResidualCapacities[a];
                        this.ResidualCapacities[a] -= delta;
                        this.ResidualCapacities[this.ReversedEdges[a]] += delta;
                        this.excessFlow[a.Target] += delta;
                    }
                }
            }

            maxDistance = VisitedGraph.VerticesCount - 1;
            maxActive = 0;
            minActive = n;

            foreach (IVertex u in this.VisitedGraph.Vertices)
            {
                if (u == sink)
                {
                    distances[u] = 0;
                    continue;
                }
                else if (u == src && !overflowDetected)
                {
                    distances[u] = n;
                }
                else
                {
                    distances[u] = 1;
                }

                if (excessFlow[u] > 0)
                    this.AddToActiveList(u, layers[1]);
                else if (distances[u] < n)
                    this.AddToInactiveList(u, layers[1]);
            }
        }
 private void AddToInactiveList(IVertex u, PreflowLayer layer)
 {
     layer.InactiveVertices.Insert(0, u);
 }
 private void AddToActiveList(IVertex u, PreflowLayer layer)
 {
     layer.ActiveVertices.Insert(0, u);
     maxActive = Math.Max(Distances[u], maxActive);
     minActive = Math.Min(Distances[u], minActive);
 }
 private void AddToInactiveList(IVertex u, PreflowLayer layer)
 {
     layer.InactiveVertices.Insert(0, u);
 }
 private void AddToActiveList(IVertex u, PreflowLayer layer)
 {
     layer.ActiveVertices.Insert(0, u);
     maxActive = Math.Max(Distances[u], maxActive);
     minActive = Math.Min(Distances[u], minActive);
 }
        private void Initialize()
        {
            int m = 0;

            n = VisitedGraph.VerticesCount;
            foreach (IVertex u in VisitedGraph.Vertices)
            {
                m += VisitedGraph.OutDegree(u);
            }
            // Don't count the reverse edges
            m /= 2;
            nm = alpha * n + m;

            excessFlow.Clear();
            current.Clear();
            distances.Clear();

            layers = new PreflowLayer[n];
            for (int i = 0; i < n; i++)
            {
                layers[i] = new PreflowLayer();
            }

            // Initialize flow to zero which means initializing
            // the residual capacity to equal the capacity.
            foreach (IVertex u in VisitedGraph.Vertices)
            {
                foreach (IEdge e in VisitedGraph.OutEdges(u))
                {
                    this.ResidualCapacities[e] = this.Capacities[e];
                }

                excessFlow[u] = 0;
                current[u]    = 0;
            }

            bool   overflowDetected = false;
            double testExcess       = 0;

            foreach (IEdge a in VisitedGraph.OutEdges(src))
            {
                if (a.Target != src)
                {
                    testExcess += this.ResidualCapacities[a];
                }
            }

            if (testExcess >= double.MaxValue || double.IsPositiveInfinity(testExcess))
            {
                overflowDetected = true;
            }

            if (overflowDetected)
            {
                excessFlow[src] = double.MaxValue;
            }
            else
            {
                excessFlow[src] = 0;
                foreach (IEdge a in this.VisitedGraph.OutEdges(src))
                {
                    if (a.Target != src)
                    {
                        double delta = this.ResidualCapacities[a];
                        this.ResidualCapacities[a] -= delta;
                        this.ResidualCapacities[this.ReversedEdges[a]] += delta;
                        this.excessFlow[a.Target] += delta;
                    }
                }
            }

            maxDistance = VisitedGraph.VerticesCount - 1;
            maxActive   = 0;
            minActive   = n;

            foreach (IVertex u in this.VisitedGraph.Vertices)
            {
                if (u == sink)
                {
                    distances[u] = 0;
                    continue;
                }
                else if (u == src && !overflowDetected)
                {
                    distances[u] = n;
                }
                else
                {
                    distances[u] = 1;
                }

                if (excessFlow[u] > 0)
                {
                    this.AddToActiveList(u, layers[1]);
                }
                else if (distances[u] < n)
                {
                    this.AddToInactiveList(u, layers[1]);
                }
            }
        }
 private void AddToActiveList(IVertex u, PreflowLayer layer)
 {
     layer.ActiveVertices.Insert(0, u);
     this.maxActive = Math.Max(this.Distances.get_Item(u), this.maxActive);
     this.minActive = Math.Min(this.Distances.get_Item(u), this.minActive);
 }