// O(E*log(N))
        public static ulong[] Dijkstra(IList<N> nodes, int fromNode)
        {
            var dist = new ulong[nodes.Count];
            var heap = new BinaryHeapWithUpdates<ulong, int>(Comparer<ulong>.Default, EqualityComparer<int>.Default);
            for (int i = 0; i < dist.Length; i++)
                dist[i] = ulong.MaxValue;

            dist[fromNode] = 0;
            heap.Insert(0, fromNode);
            while (!heap.IsEmpty())
            {
                var min = heap.ExtractMin();
                foreach (E edge in nodes[min.Value].Edges)
                {
                    ulong d = min.Key + edge.Length;
                    if (d < dist[edge.ToNode])
                    {
                        if (dist[edge.ToNode] == ulong.MaxValue)
                            heap.Insert(d, edge.ToNode);
                        else
                            heap.UpdateKey(edge.ToNode, d);

                        dist[edge.ToNode] = d;
                    }
                }
            }

            return dist;
        }
        public void UpdateKeyTest(string[] keys, string oldKey, string newKey)
        {
            var keyComparer = StringComparer.Ordinal;
            var valueComparer = EqualityComparer<int>.Default;

            var heap = new BinaryHeapWithUpdates<string, int>(keyComparer, valueComparer);
            var pairs = new List<KeyValuePair<string, int>>();
            foreach (var key in keys)
            {
                int value = key.GetHashCode();
                heap.Insert(key, value);
                pairs.Add(new KeyValuePair<string, int>(key, value));
            }

            int oldKeyIndex = Array.IndexOf(keys, oldKey);
            int oldValue = pairs[oldKeyIndex].Value;
            pairs[oldKeyIndex] = new KeyValuePair<string, int>(newKey, oldValue);

            heap.UpdateKey(oldValue, newKey);

            var expected = pairs.OrderBy(p => p.Key, keyComparer).ToArray();
            for (int i = 0; i < keys.Length; i++)
            {
                var min = heap.ExtractMin();
                Assert.Equal(expected[i], min);
            }
        }
        // O(E*log(N))
        public static Dictionary<Node, ulong> Dijkstra(Node from)
        {
            var dist = new Dictionary<Node, ulong>();
            var heap = new BinaryHeapWithUpdates<ulong, Node>(Comparer<ulong>.Default, EqualityComparer<Node>.Default);
            dist.Add(from, 0);
            heap.Insert(0, from);

            while (!heap.IsEmpty())
            {
                var min = heap.ExtractMin();
                foreach (var edge in min.Value.Edges)
                {
                    ulong newDistance = min.Key + edge.Length;
                    if (!dist.ContainsKey(edge.ToNode))
                    {
                        dist.Add(edge.ToNode, newDistance);
                        heap.Insert(newDistance, edge.ToNode);
                    }
                    else if (newDistance < dist[edge.ToNode])
                    {
                        dist[edge.ToNode] = newDistance;
                        heap.UpdateKey(edge.ToNode, newDistance);
                    }
                }
            }

            return dist;
        }