/// <summary>
        ///     Uses Kruskal's algorithm to build an MST spanning the mstNodes
        ///     with the given edges as a list ordered by priority ascending.
        ///     The edges don't need to contain only nodes given to this instance
        ///     via constructor.
        ///     O(|edges|) runtime.
        /// </summary>
        /// <param name="ordererdEdges">Edges ordered by priority ascending.</param>
        /// <remarks>
        ///     Both Span methods have quadratic runtime in the graph nodes. This one
        ///     has a lower constant factor but needs to filter out unneeded edges (quadratic
        ///     in all nodes), the other one doesn't need to do any filtering (quadratic in
        ///     considered nodes) so if the mst nodes are generally only a very small
        ///     portion of all nodes, use the other Span method, if not, use this one.
        /// </remarks>
        public void Span(IEnumerable <DirectedGraphEdge> ordererdEdges)
        {
            var mstEdges   = new List <DirectedGraphEdge>(_mstNodes.Count);
            var set        = new DisjointSet(_distances.CacheSize);
            var considered = new bool[_distances.CacheSize];
            var toAddCount = _mstNodes.Count - 1;

            foreach (var t in _mstNodes)
            {
                considered[t] = true;
            }
            foreach (var current in ordererdEdges)
            {
                var inside  = current.Inside;
                var outside = current.Outside;
                // This condition is by far the bottleneck of the method.
                // (most likely because branch prediction can't predict the result)
                if (!considered[inside] | !considered[outside])
                {
                    continue;
                }
                if (set.Find(inside) == set.Find(outside))
                {
                    continue;
                }
                mstEdges.Add(current);
                set.Union(inside, outside);
                if (--toAddCount == 0)
                {
                    break;
                }
            }
            SpanningEdges = mstEdges;
        }
        /// <summary>
        /// Uses Kruskal's algorithm to build an MST spanning the mstNodes
        /// with the given edges as a linked list ordered by priority ascending.
        /// The edges don't need to contain only nodes given to this instance
        /// via constructor.
        /// O(|edges|) runtime.
        /// </summary>
        /// <param name="first">First edge of the linked list.</param>
        /// <remarks>
        /// Both Span methods have quadratic runtime in the graph nodes. This one
        /// has a lower constant factor but needs to filter out unneeded edges (quadratic
        /// in all nodes), the other one doesn't need to do any filtering (quadratic in
        /// considered nodes) so if the mst nodes are generally only a very small
        /// portion of all nodes, use the other Span method, if not, use this one.
        /// </remarks>
        public void Span(LinkedGraphEdge first)
        {
            var mstEdges   = new List <GraphEdge>(_mstNodes.Count);
            var set        = new DisjointSet(_distances.CacheSize);
            var considered = new bool[_distances.CacheSize];
            var toAddCount = _mstNodes.Count - 1;

            foreach (var t in _mstNodes)
            {
                considered[t.DistancesIndex] = true;
            }
            for (var current = first; current != null; current = current.Next)
            {
                var inside  = current.Inside;
                var outside = current.Outside;
                // This condition is by far the bottleneck of the method.
                // (most likely because branch prediction can't predict the result)
                if (!considered[inside] | !considered[outside])
                {
                    continue;
                }
                if (set.Find(inside) == set.Find(outside))
                {
                    continue;
                }
                mstEdges.Add(new GraphEdge(_distances.IndexToNode(inside), _distances.IndexToNode(outside)));
                set.Union(inside, outside);
                if (--toAddCount == 0)
                {
                    break;
                }
            }
            SpanningEdges = mstEdges;
            IsSpanned     = true;
        }
 /// <summary>
 ///     Uses Kruskal's algorithm to build an MST spanning the mstNodes
 ///     with the given edges as a list ordered by priority ascending.
 ///     The edges don't need to contain only nodes given to this instance
 ///     via constructor.
 ///     O(|edges|) runtime.
 /// </summary>
 /// <param name="ordererdEdges">Edges ordered by priority ascending.</param>
 /// <remarks>
 ///     Both Span methods have quadratic runtime in the graph nodes. This one
 ///     has a lower constant factor but needs to filter out unneeded edges (quadratic
 ///     in all nodes), the other one doesn't need to do any filtering (quadratic in
 ///     considered nodes) so if the mst nodes are generally only a very small
 ///     portion of all nodes, use the other Span method, if not, use this one.
 /// </remarks>
 public void Span(IEnumerable<DirectedGraphEdge> ordererdEdges)
 {
     var mstEdges = new List<DirectedGraphEdge>(_mstNodes.Count);
     var set = new DisjointSet(_distances.CacheSize);
     var considered = new bool[_distances.CacheSize];
     var toAddCount = _mstNodes.Count - 1;
     foreach (var t in _mstNodes)
     {
         considered[t] = true;
     }
     foreach (var current in ordererdEdges)
     {
         var inside = current.Inside;
         var outside = current.Outside;
         // This condition is by far the bottleneck of the method.
         // (most likely because branch prediction can't predict the result)
         if (!considered[inside] | !considered[outside]) continue;
         if (set.Find(inside) == set.Find(outside)) continue;
         mstEdges.Add(current);
         set.Union(inside, outside);
         if (--toAddCount == 0) break;
     }
     SpanningEdges = mstEdges;
 }