public long[] CalcShortestPathsByHeap(EdgeEndPoint[][] adjacencyList, int v)
        {
            var vertices = adjacencyList
                           .Select(p => new VertexInfo {
                Path = long.MaxValue, Adjacents = p
            })
                           .ToArray();

            vertices[v].Path = 0;

            var front = new GenericBinaryHeap <VertexInfo>(
                (x, y) => x.Path.CompareTo(y.Path),
                (vi, i) => vi.IndexInHeap = i);

            front.Insert(vertices[v]);

            while (front.Count > 0)
            {
                var u = front.Min;

                front.DeleteMin();

                if (u.Visited)
                {
                    continue;
                }

                u.Visited = true;

                foreach (var edge in u.Adjacents)
                {
                    var to = vertices[edge.To];

                    if (to.Visited)
                    {
                        continue;
                    }

                    var w = u.Path + edge.Weight;

                    if (w < to.Path)
                    {
                        if (front.Count > 0 && front[to.IndexInHeap] == to)
                        {
                            front.Remove(to.IndexInHeap);
                        }
                        to.Path = w;
                    }

                    front.Insert(to);
                }
            }

            return(vertices.Select(vi => vi.Path).ToArray());
        }
        public List <Edge> Prim(List <Edge>[] graph)
        {
            // O(m * log n), m edges, n vertices

            var mst = new List <Edge>();

            var start = new Random().Next(graph.Length - 1) + 1;

            var visited = new bool[graph.Length];

            visited[start] = true;

            var heap = new GenericBinaryHeap <VertexInfo>(
                (x, y) => x.Cost.CompareTo(y.Cost),
                (info, index) => info.IndexInHeap = index);

            var infos = new VertexInfo[graph.Length];

            for (var i = 0; i < infos.Length; i++)
            {
                if (graph[i] != null && i != start)
                {
                    infos[i] = new VertexInfo {
                        Cost = long.MaxValue
                    }
                }
            }
            ;

            heap.FillRaw(infos.Where(i => i != null));

            foreach (var edge in graph[start])
            {
                var vertexInfo = infos[edge.To];
                vertexInfo.KeyEdge = edge;
                vertexInfo.Cost    = edge.Weight;
                heap.BubbleUp(vertexInfo.IndexInHeap);
            }

            while (heap.Count > 0)
            {
                var uv = heap.Min.KeyEdge;

                mst.Add(uv);

                heap.DeleteMin();

                visited[uv.To] = true;

                foreach (var edge in graph[uv.To])
                {
                    if (!visited[edge.To])
                    {
                        var info = infos[edge.To];
                        if (edge.Weight < info.Cost)
                        {
                            info.Cost    = edge.Weight;
                            info.KeyEdge = edge;
                            heap.BubbleUp(info.IndexInHeap);
                        }
                    }
                }
            }

            return(mst);
        }