/// <summary>
        /// Prim's algorithm to find the minimum span tree on graph
        /// </summary>
        /// <param name="graph"> <see cref="Graph"/> instance. </param>
        /// <returns> Minimum span tree containing edges and minimum distance. </returns>
        public static MinimumSpanTree <T> PrimsMinimumSpanningTree <T>(this DirectedGraph <T> graph) where T : IEquatable <T>
        {
            if (graph.Vertices.Count == 0 || graph.Edges.Count == 0)
            {
                return(new MinimumSpanTree <T>(Enumerable.Empty <Edge <T> >().ToList(), 0));
            }

            var currentVertex   = graph.Vertices.First();
            int minimumDistance = 0;
            var minimumSpanTree = new List <Edge <T> >();
            var edgesToVisit    = new BinaryHeap <Edge <T> >(BinaryHeapType.MinimumHeap, currentVertex.OutboundEdges.Count, new EdgeComparer <T>());
            var verticesVisited = new HashSet <Vertex <T> >();

            while (minimumSpanTree.Count < graph.Vertices.Count - 1)
            {
                foreach (var edge in currentVertex.OutboundEdges)
                {
                    edgesToVisit.Add(edge);
                }

                verticesVisited.Add(currentVertex);
                Edge <T> minimumEdge = null;

                while (edgesToVisit.Count > 0)
                {
                    minimumEdge = edgesToVisit.Remove();
                    if (verticesVisited.Contains(minimumEdge.StartVertex) != verticesVisited.Contains(minimumEdge.EndVertex))
                    {
                        break;
                    }
                }

                if (minimumEdge == null)
                {
                    throw new MultipleMinimumSpanningTreesException();
                }

                minimumSpanTree.Add(minimumEdge);
                minimumDistance += minimumEdge.Weight;
                currentVertex    = verticesVisited.Contains(minimumEdge.EndVertex)
                                      ? minimumEdge.StartVertex
                                      : minimumEdge.EndVertex;
            }

            return(new MinimumSpanTree <T>(minimumSpanTree, minimumDistance));
        }
        /// <summary>
        /// Kruskal's algorithm to find the minimum span tree on graph
        /// </summary>
        /// <param name="graph"> <see cref="Graph"/> instance. </param>
        /// <returns> Minimum span tree containing edges and minimum distance. </returns>
        public static MinimumSpanTree <T> KruskalsMinimumSpanningTree <T>(this DirectedGraph <T> graph) where T : IEquatable <T>
        {
            if (graph.Vertices.Count == 0 || graph.Edges.Count == 0)
            {
                return(new MinimumSpanTree <T>(Enumerable.Empty <Edge <T> >().ToList(), 0));
            }

            var minimumSpanTree = new List <Edge <T> >();
            var minimumDistance = 0;
            var unionFind       = new DisjointSet <Vertex <T> >(graph.Vertices);
            var edgesToVisit    = new BinaryHeap <Edge <T> >(BinaryHeapType.MinimumHeap, graph.Edges.Count, new EdgeComparer <T>());

            foreach (var edge in graph.Edges)
            {
                edgesToVisit.Add(edge);
            }

            while (minimumSpanTree.Count < graph.Vertices.Count - 1)
            {
                Edge <T> minimumEdge = null;

                while (edgesToVisit.Count > 0)
                {
                    minimumEdge = edgesToVisit.Remove();
                    if (unionFind.Find(minimumEdge.StartVertex) != unionFind.Find(minimumEdge.EndVertex))
                    {
                        break;
                    }
                }

                if (minimumEdge == null)
                {
                    throw new MultipleMinimumSpanningTreesException();
                }

                minimumSpanTree.Add(minimumEdge);
                minimumDistance += minimumEdge.Weight;
                unionFind.Union(minimumEdge.StartVertex, minimumEdge.EndVertex);
            }

            return(new MinimumSpanTree <T>(minimumSpanTree, minimumDistance));
        }