/// <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 Prim's algorithm to build an MST spanning the mstNodes.
        ///  O(|mstNodes|^2) runtime.
        /// </summary>
        /// <param name="startFrom">A GraphNode to start from.</param>
        public void Span(GraphNode startFrom)
        {
            var adjacentEdgeQueue = new LinkedListPriorityQueue <LinkedGraphEdge>(100);

            var startIndex = startFrom.DistancesIndex;
            // All nodes that are not yet included.
            var toAdd = new List <int>(_mstNodes.Count);
            // If the index node is already included.
            var inMst = new bool[_distances.CacheSize];
            // The spanning edges.
            var mstEdges = new List <GraphEdge>(_mstNodes.Count);

            for (var i = 0; i < _mstNodes.Count; i++)
            {
                var index = _mstNodes[i].DistancesIndex;
                if (index != startIndex)
                {
                    toAdd.Add(index);
                    var adjacentEdge = new LinkedGraphEdge(startIndex, index);
                    adjacentEdgeQueue.Enqueue(adjacentEdge, _distances[startIndex, index]);
                }
            }
            inMst[startIndex] = true;

            while (toAdd.Count > 0 && adjacentEdgeQueue.Count > 0)
            {
                int             newIn;
                LinkedGraphEdge shortestEdge;
                // Dequeue and ignore edges that are already inside the MST.
                // Add the first one that is not.
                do
                {
                    shortestEdge = adjacentEdgeQueue.Dequeue();
                    newIn        = shortestEdge.Outside;
                } while (inMst[newIn]);
                mstEdges.Add(new GraphEdge(
                                 _distances.IndexToNode(shortestEdge.Inside),
                                 _distances.IndexToNode(shortestEdge.Outside)));
                inMst[newIn] = true;

                // Find all newly adjacent edges and enqueue them.
                for (var i = 0; i < toAdd.Count; i++)
                {
                    var otherNode = toAdd[i];
                    if (otherNode == newIn)
                    {
                        toAdd.RemoveAt(i--);
                    }
                    else
                    {
                        var edge = new LinkedGraphEdge(newIn, otherNode);
                        adjacentEdgeQueue.Enqueue(edge, _distances[newIn, otherNode]);
                    }
                }
            }

            SpanningEdges = mstEdges;
            IsSpanned     = true;
        }