public static Graph <VisVertex> GetMST_KrusculDSU(Graph <VisVertex> graph)
        {
            Edge <VisVertex>[] sortedEdges = GetSortedEdges(graph.EdgesClone);
            Graph <VisVertex>  mst         = new Graph <VisVertex>(graph.VerticesClone);//Создаем МОД
            DisjointSet        dsu         = new DisjointSet(graph.Order);

            foreach (Edge <VisVertex> edge in sortedEdges)
            {
                if (mst.EdgesCount == graph.Order - 1)
                {
                    break;                                   //Если МОД построен выходим из цикла
                }
                if (dsu.InTheSameSet(edge.V1Id, edge.V2Id))
                {
                    continue;
                }
                //Если вершины ребра в одной компоненте пропускаем ребро
                mst.AddEdge(edge);                   //Добавляем ребро мнимального веса в МОД
                dsu.UnionSets(edge.V1Id, edge.V2Id); //Объединяем связанные компоненты
            }
            if (mst.EdgesCount != graph.Order - 1)
            {
                throw new Exception("Ошибка МОД не найдено");
            }
            return(mst);
        }
        public async void KrusculAlgorithmVisAsync()
        {
            if (!graph.IsConnected)
            {
                visualisator.Print("Остовное дерево не может быть построено. Граф не связен!");
                visualisator.ApEndLog("Остовное дерево не может быть построено. Граф не связен!");
                return;
            }
            form.BlockTabControl();
            int order = graph.Order;

            Edge <VisVertex>[] sortedEdges = GetSortedEdges(graph.EdgesClone);
            Graph <VisVertex>  mst         = new Graph <VisVertex>(graph.VerticesClone);//Создаем МОД
            DisjointSet        dsu         = new DisjointSet(order);

            SetVerticesDifferentColors();
            visualisator.Print("Маркировка вершин");
            visualisator.ApEndLog("МОД сотоит из отдельных вершин - компонент связности, " +
                                  "маркированных различными цветами" +
                                  "\nПоследовательно простомтрим ребра, отсортированные по неубыванию веса.");
            visualisator.PrintDataStructuresKruskal(sortedEdges, sortedEdges[0], dsu, colors);
            await Task.Delay(SleepInterval);

            foreach (Edge <VisVertex> edge in sortedEdges)
            {
                if (mst.EdgesCount == order - 1)
                {
                    break;                             //Если МОД построен выходим из цикла
                }
                if (dsu.InTheSameSet(edge.V1Id, edge.V2Id))
                {
                    visualisator.ApEndLog(
                        $"Ребро {edge} соединяет вершины из одной компоненты - пропускаем.");
                    visualisator.PrintDataStructuresKruskal(sortedEdges, edge, dsu, colors);
                    await Task.Delay(SleepInterval);

                    continue;                        //Если вершины ребра в одной компоненте пропускаем ребро
                }
                mst.AddEdge(edge);                   //Добавляем ребро мнимального веса в МОД
                dsu.UnionSets(edge.V1Id, edge.V2Id); //Объединяем связанные компоненты

                RefreshColors(dsu, mst);
                visualisator.Print($"Добавление ребра минимального веса. " +
                                   $"Всего ребер {mst.EdgesCount}. Общий вес {mst.TotalWeight}.");
                visualisator.ApEndLog(
                    $"Ребро {edge} соединяет вершины из разных компонент - добавляем в МОД. " +
                    $"Объединяем связанные ребром компоненты.");
                visualisator.PrintDataStructuresKruskal(sortedEdges, edge, dsu, colors);
                await Task.Delay(SleepInterval);
            }
            if (mst.EdgesCount != order - 1)
            {
                throw new Exception("Ошибка МОД не найдено");
            }
            else
            {
                visualisator.Print(
                    $"Минимальное остовное дерево построено. Общий вес {mst.TotalWeight}.");
                visualisator.ApEndLog(
                    $"Минимальное остовное дерево построено. Общий вес {mst.TotalWeight}.");
            }
            form.UnBlockTabControl();
        }