public static Graph Kruskal(Graph inputGraph)
        {
            var result = new Graph();
            result.Vertexes = inputGraph.Vertexes;

            var edges = inputGraph.Edges.ToList();
            edges.Sort();
            var enumerator = edges.GetEnumerator();

            var disjointSetUnion = new DisjointSetUnionTree(inputGraph.Vertexes);

            while (result.Edges.Count < result.Vertexes.Count - 1) {
                enumerator.MoveNext();
                var edge = enumerator.Current;

                var fromRoot = disjointSetUnion.Find(edge.From);
                var toRoot = disjointSetUnion.Find(edge.To);

                if (fromRoot != toRoot) {
                    disjointSetUnion.Union(edge.From, edge.To);
                    result.Edges.Add(edge);
                }
            }

            return result;
        }
        public static Graph Boruvka(Graph graph)
        {
            var result = new Graph();
            result.Vertexes = graph.Vertexes;

            var disjointForest = new DisjointSetUnionTree(result.Vertexes);

            while (result.Edges.Count < result.Vertexes.Count - 1) {
                var safe = new Dictionary<int, Edge<int>>();

                foreach (var edge in graph.Edges) {
                    var fromRoot = disjointForest.Find(edge.From);
                    var toRoot = disjointForest.Find(edge.To);

                    if (fromRoot != toRoot) {
                        if (!safe.ContainsKey(fromRoot) || edge.Weight < safe[fromRoot].Weight) {
                            safe[fromRoot] = edge;
                        }

                        if (!safe.ContainsKey(toRoot) || edge.Weight < safe[toRoot].Weight) {
                            safe[toRoot] = edge;
                        }
                    }
                }

                result.Edges.AddRange(safe.Values.Distinct());

                foreach (var edge in safe.Values) {
                    disjointForest.Union(edge.From, edge.To);
                }
            }

            return result;
        }
        public static int Cluster(Graph graph, int clusterCount)
        {
            var result = new Graph {
                                       Vertexes = graph.Vertexes
                                   };

            var edges = graph.Edges.ToList();
            edges.Sort();
            var enumerator = edges.GetEnumerator();

            var disjointSetUnion = new DisjointSetUnionTree(graph.Vertexes);

            while (disjointSetUnion.Count != clusterCount - 1) {
                enumerator.MoveNext();
                var edge = enumerator.Current;

                var fromRoot = disjointSetUnion.Find(edge.From);
                var toRoot = disjointSetUnion.Find(edge.To);

                if (fromRoot != toRoot) {
                    disjointSetUnion.Union(fromRoot, toRoot);
                    result.Edges.Add(edge);
                }
            }

            return enumerator.Current.Weight;
        }
        public static Graph GenerateFullGraph(int vertexes, int weightFrom, int weightTo)
        {
            var result = new Graph();

            for (var i = 0; i < vertexes; i++) {
                result.Vertexes.Add(i);
            }

            for (var i = 0; i < vertexes; i++) {
                for (var j = i + 1; j < vertexes; j++) {
                    var weight = random.Next(weightFrom, weightTo + 1);
                    result.Edges.Add(new Edge<int>(i, j, weight));
                }
            }

            return result;
        }
        public static Graph NaivePrim(Graph inputGraph)
        {
            var result = new Graph();
            result.Vertexes.Add(inputGraph.Vertexes.First());

            while (result.Vertexes.Count != inputGraph.Vertexes.Count) {
                var newEdge = inputGraph
                    .Edges
                    .Where(_ => result.Vertexes.Contains(_.From) ^ result.Vertexes.Contains(_.To))
                    .Min();

                result.Edges.Add(newEdge);
                result.Vertexes.Add(result.Vertexes.Contains(newEdge.From) ? newEdge.To : newEdge.From);
            }

            return result;
        }
        public static Graph GenerateFromFile(string path)
        {
            var reader = new StreamReader(path);
            var firstLine = reader.ReadLine().Split(' ');
            var vertexes = Convert.ToInt32(firstLine[0]);
            var edges = Convert.ToInt32(firstLine[1]);

            var graph = new Graph {
                Vertexes = Enumerable.Range(0, vertexes).ToList()
            };

            for (var i = 0; i < edges; i++) {
                var line = reader.ReadLine().Split(' ');
                var from = Convert.ToInt32(line[0]) - 1;
                var to = Convert.ToInt32(line[1]) - 1;
                var weight = Convert.ToInt32(line[2]);
                graph.Edges.Add(new Edge<int>(from, to, weight));
            }

            return graph;
        }
 public void Init()
 {
     inputGraph = new Graph();
     inputGraph.Vertexes.Add(0);
     inputGraph.Vertexes.Add(1);
     inputGraph.Vertexes.Add(2);
     inputGraph.Vertexes.Add(3);
     inputGraph.Vertexes.Add(4);
     inputGraph.Vertexes.Add(5);
     inputGraph.Vertexes.Add(6);
     inputGraph.Vertexes.Add(7);
     inputGraph.Edges.Add(new Edge<int>(0, 1, 6));
     inputGraph.Edges.Add(new Edge<int>(0, 2, 11));
     inputGraph.Edges.Add(new Edge<int>(0, 3, 17));
     inputGraph.Edges.Add(new Edge<int>(1, 2, 25));
     inputGraph.Edges.Add(new Edge<int>(3, 2, 8));
     inputGraph.Edges.Add(new Edge<int>(7, 2, 2));
     inputGraph.Edges.Add(new Edge<int>(7, 5, 14));
     inputGraph.Edges.Add(new Edge<int>(7, 6, 21));
     inputGraph.Edges.Add(new Edge<int>(4, 5, 9));
     inputGraph.Edges.Add(new Edge<int>(4, 1, 19));
 }
        public static Graph Kruskal(Graph inputGraph)
        {
            var result = new Graph();
            result.Vertexes = inputGraph.Vertexes;

            var edges = inputGraph.Edges.ToList();
            edges.Sort(new WeightComparer<int>());

            var disjointSetUnion = new DisjointSetUnionTree(inputGraph.Vertexes);

            foreach (var edge in edges) {
                var fromRoot = disjointSetUnion.Find(edge.From);
                var toRoot = disjointSetUnion.Find(edge.To);

                if (fromRoot != toRoot) {
                    disjointSetUnion.Union(fromRoot, toRoot);
                    result.Edges.Add(edge);
                }
            }

            return result;
        }
        public static Graph GenerateTree(int vertexes)
        {
            var result = new Graph();

            for (var i = 0; i < vertexes; i++) {
                result.Vertexes.Add(i);
            }

            var disjointSet = new DisjointSetUnionTree(result.Vertexes);

            while (result.Edges.Count < result.Vertexes.Count - 1) {
                var from = random.Next(vertexes);
                var to = random.Next(vertexes);

                if (from == to || disjointSet.Find(from) == disjointSet.Find(to)) continue;

                result.Edges.Add(new Edge<int>(from, to, 0));
                disjointSet.Union(from, to);
            }

            return result;
        }
 private static void AssertSimpleSpanningTree(Graph graph)
 {
     Assert.AreEqual(8, graph.Vertexes.Count);
     Assert.AreEqual(7, graph.Edges.Count);
     Assert.AreEqual(71, graph.Weight);
 }