/// <summary>
        /// Computes the number of eulerian trail in the graph.
        /// </summary>
        /// <param name="g"></param>
        /// <returns>number of eulerian trails</returns>
        public static int ComputeEulerianPathCount(IVertexAndEdgeListGraph <TVertex, TEdge> g)
        {
            if (g == null)
            {
                throw new ArgumentNullException("g");
            }

            if (g.EdgeCount < g.VertexCount)
            {
                return(0);
            }

            int odd = AlgoUtility.OddVertices(g).Count;

            if (odd == 0)
            {
                return(1);
            }
            else if (odd % 2 != 0)
            {
                return(0);
            }
            else
            {
                return(odd / 2);
            }
        }
        /// <summary>
        /// Adds temporary edges to the graph to make all vertex even.
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        public List <TEdge> AddTemporaryEdges(IEdgeFactory <TVertex, TEdge> edgeFactory)
        {
            // first gather odd edges.
            List <TVertex> oddVertices = AlgoUtility.OddVertices(this.VisitedGraph);

            // check that there are an even number of them
            if (oddVertices.Count % 2 != 0)
            {
                throw new Exception("number of odd vertices in not even!");
            }

            // add temporary edges to create even edges:
            this.temporaryEdges = new List <TEdge>();

            bool found, foundbe, foundadjacent;

            while (oddVertices.Count > 0)
            {
                TVertex u = oddVertices[0];
                // find adjacent odd vertex.
                found         = false;
                foundadjacent = false;
                foreach (var e in this.VisitedGraph.OutEdges(u))
                {
                    TVertex v = e.Target;
                    if (!v.Equals(u) && oddVertices.Contains(v))
                    {
                        foundadjacent = true;
                        // check that v does not have an out-edge towards u
                        foundbe = false;
                        foreach (var be in this.VisitedGraph.OutEdges(v))
                        {
                            if (be.Target.Equals(u))
                            {
                                foundbe = true;
                                break;
                            }
                        }
                        if (foundbe)
                        {
                            continue;
                        }
                        // add temporary edge
                        TEdge tempEdge = edgeFactory.CreateEdge(v, u);
                        if (!this.VisitedGraph.AddEdge(tempEdge))
                        {
                            throw new InvalidOperationException();
                        }
                        // add to collection
                        temporaryEdges.Add(tempEdge);
                        // remove u,v from oddVertices
                        oddVertices.Remove(u);
                        oddVertices.Remove(v);
                        // set u to null
                        found = true;
                        break;
                    }
                }

                if (!foundadjacent)
                {
                    // pick another vertex
                    if (oddVertices.Count < 2)
                    {
                        throw new Exception("Eulerian trail failure");
                    }
                    TVertex v        = oddVertices[1];
                    TEdge   tempEdge = edgeFactory.CreateEdge(u, v);
                    if (!this.VisitedGraph.AddEdge(tempEdge))
                    {
                        throw new InvalidOperationException();
                    }
                    // add to collection
                    temporaryEdges.Add(tempEdge);
                    // remove u,v from oddVertices
                    oddVertices.Remove(u);
                    oddVertices.Remove(v);
                    // set u to null
                    found = true;
                }

                if (!found)
                {
                    oddVertices.Remove(u);
                    oddVertices.Add(u);
                }
            }
            return(this.temporaryEdges);
        }
        protected override void InternalCompute()
        {
            var cancelManager = this.Services.CancelManager;

            this.matchedEdges.Clear();
            AllVerticesGraphAugmentorAlgorithm <TVertex, TEdge> augmentor = null;
            ReversedEdgeAugmentorAlgorithm <TVertex, TEdge>     reverser  = null;

            try
            {
                if (cancelManager.IsCancelling)
                {
                    return;
                }

                //augmenting graph
                augmentor = new AllVerticesGraphAugmentorAlgorithm <TVertex, TEdge>(
                    this,
                    this.VisitedGraph,
                    this.VertexFactory,
                    this.EdgeFactory);
                augmentor.Compute();
                if (cancelManager.IsCancelling)
                {
                    return;
                }


                // adding reverse edges
                reverser = new ReversedEdgeAugmentorAlgorithm <TVertex, TEdge>(
                    this,
                    this.VisitedGraph,
                    this.EdgeFactory
                    );
                reverser.AddReversedEdges();
                if (cancelManager.IsCancelling)
                {
                    return;
                }


                // compute maxflow
                var flow = new EdmondsKarpMaximumFlowAlgorithm <TVertex, TEdge>(
                    this,
                    this.VisitedGraph,
                    AlgoUtility.ConstantCapacities(this.VisitedGraph, 1),
                    reverser.ReversedEdges
                    );
                flow.Compute(augmentor.SuperSource, augmentor.SuperSink);
                if (cancelManager.IsCancelling)
                {
                    return;
                }


                foreach (var edge in this.VisitedGraph.Edges)
                {
                    if (cancelManager.IsCancelling)
                    {
                        return;
                    }

                    if (flow.ResidualCapacities[edge] == 0)
                    {
                        this.matchedEdges.Add(edge);
                    }
                }
            }
            finally
            {
                if (reverser != null && reverser.Augmented)
                {
                    reverser.RemoveReversedEdges();
                    reverser = null;
                }
                if (augmentor != null && augmentor.Augmented)
                {
                    augmentor.Rollback();
                    augmentor = null;
                }
            }
        }