コード例 #1
0
        //Część 3
        // Wyznaczanie minimalnego drzewa (bądź lasu) rozpinającego algorytmem Kruskala
        // 2 pkt
        public Graph MinimumSpanningTree(Graph graph, out double min_weight)
        {
            if (graph.Directed)
            {
                throw new ArgumentException();
            }

            UnionFind             u = new UnionFind(graph.VerticesCount);
            EdgesMinPriorityQueue q = new EdgesMinPriorityQueue();
            Graph kurskalTree       = graph.IsolatedVerticesGraph();

            for (int i = 0; i < graph.VerticesCount; i++)
            {
                foreach (var e in graph.OutEdges(i))
                {
                    if (e.To >= i)
                    {
                        q.Put(e);
                    }
                }
            }
            min_weight = 0;       // zmienić
            while (!q.Empty)
            {
                Edge e = q.Get();
                if (u.Union(e.From, e.To))
                {
                    kurskalTree.AddEdge(e);
                    min_weight += e.Weight;
                }
            }
            return(kurskalTree);  // zmienić
        }
コード例 #2
0
        // Część 3
        // Wyznaczanie minimalnego drzewa rozpinającego algorytmem Kruskala
        //   1.5 pkt
        // Schemat algorytmu Kruskala
        //   1) wrzucić wszystkie krawędzie do "wspólnego worka"
        //   2) wyciągać z "worka" krawędzie w kolejności wzrastających wag
        //      - jeśli krawędź można dodać do drzewa to dodawać, jeśli nie można to ignorować
        //      - punkt 2 powtarzać aż do skonstruowania drzewa (lub wyczerpania krawędzi)
        // Parametry:
        //   g - graf wejściowy
        //   mstw - waga skonstruowanego drzewa (lasu)
        // Wynik:
        //   skonstruowane minimalne drzewo rozpinające (albo las)
        // Uwagi:
        //   1) Metoda uruchomiona dla grafu skierowanego powinna zgłaszać wyjątek Lab03Exception
        //   2) Graf wejściowy pozostaje niezmieniony
        //   3) Wykorzystać klasę UnionFind z biblioteki Graph
        //   4) Jeśli graf g jest niespójny to metoda wyznacza las rozpinający
        //   5) Graf wynikowy (drzewo) musi być w takiej samej reprezentacji jak wejściowy
        public static Graph Lab03Kruskal(this Graph g, out int mstw)
        {
            mstw = 0;
            if (g.Directed == true)
            {
                throw new Lab03Exception();
            }

            // Dodanie krawedzi do kolejki:
            Graph ret = g.IsolatedVerticesGraph();
            EdgesMinPriorityQueue pq = new EdgesMinPriorityQueue();

            for (int i = 0; i < g.VerticesCount; i++)
            {
                foreach (Edge e in g.OutEdges(i))
                {
                    if (e.To < i)
                    {
                        pq.Put(e);
                    }
                }
            }
            UnionFind vs      = new UnionFind(g.VerticesCount);
            int       vsCount = g.VerticesCount;
            Edge      ed;
            int       s1, s2;

            while (pq.Count > 0 && vsCount > 0)
            {
                //Console.WriteLine("PEEK: {0}", pq.Peek());
                ed = pq.Get();
                s1 = vs.Find(ed.From);
                s2 = vs.Find(ed.To);
                if (s1 != s2)
                {
                    vsCount--;
                    vs.Union(s1, s2);
                    ret.AddEdge(ed);
                    mstw += ed.Weight;
                    //Console.WriteLine("Weigth: {0}", mstw);
                }
            }
            return(ret);
        }
コード例 #3
0
        //Część 3
        // Wyznaczanie minimalnego drzewa (bądź lasu) rozpinającego algorytmem Kruskala
        // 2 pkt
        public Graph MinimumSpanningTree(Graph graph, out double min_weight)
        {
            if (graph.Directed == true)
            {
                throw new ArgumentException();
            }

            EdgesMinPriorityQueue edges   = new EdgesMinPriorityQueue();
            Predicate <Edge>      wyjscie = delegate(Edge a)
            {
                if (a.From < a.To)
                {
                    edges.Put(a);
                }
                return(true);
            };

            graph.GeneralSearchAll <EdgesStack>(null, null, wyjscie, out int cc);

            UnionFind union = new UnionFind(graph.VerticesCount);
            Graph     graf  = new AdjacencyListsGraph <SimpleAdjacencyList>(false, graph.VerticesCount);

            min_weight = 0;
            int ile_wstawione_krawedzi = 0;
            int ile_wierzcholkow       = graph.VerticesCount;

            while (edges.Empty == false)
            {
                Edge e = edges.Get();
                if (union.Find(e.From) != union.Find(e.To))
                {
                    union.Union(e.From, e.To);
                    graf.AddEdge(e);
                    min_weight += e.Weight;
                    ile_wstawione_krawedzi++;
                }

                if (ile_wstawione_krawedzi == ile_wierzcholkow - 1)
                {
                    break;
                }
            }
            return(graf);
        }
コード例 #4
0
ファイル: Lab03.cs プロジェクト: werglu/IsGraphic
        //Część 3
        // Wyznaczanie minimalnego drzewa (bądź lasu) rozpinającego algorytmem Kruskala

        public Graph MinimumSpanningTree(Graph graph, out double min_weight)
        {
            min_weight = 0;
            if (graph.Directed)
            {
                throw new System.ArgumentException();
            }
            int       n = graph.VerticesCount;
            UnionFind u = new UnionFind(n);

            EdgesMinPriorityQueue edges = new EdgesMinPriorityQueue();
            Graph tree = graph.IsolatedVerticesGraph();

            for (int v = 0; v < n; ++v)
            {
                foreach (Edge e in graph.OutEdges(v))
                {
                    if (e.To < e.From)
                    {
                        edges.Put(e);
                    }
                }
            }
            int count = edges.Count;

            for (; count > 0;)
            {
                Edge e = edges.Get();
                count--;
                if (u.Find(e.From) != u.Find(e.To))
                {
                    u.Union(e.From, e.To);
                    tree.Add(e);
                    min_weight += e.Weight;
                }
            }

            return(tree);
        }
コード例 #5
0
        /// <summary>
        /// Wyznacza minimalne drzewo rozpinające grafu algorytmem Kruskala
        /// </summary>
        /// <param name="g">Badany graf</param>
        /// <param name="mst">Wyznaczone drzewo rozpinające (parametr wyjściowy)</param>
        /// <returns>Waga minimalnego drzewa rozpinającego</returns>
        /// <remarks>
        /// Dla grafu skierowanego metoda zgłasza wyjątek <see cref="System.ArgumentException"/>.<br/>
        /// Wyznaczone drzewo reprezentowane jast jako graf bez cykli, to umożliwia jednolitą obsługę sytuacji
        /// gdy analizowany graf jest niespójny, wyzmnaczany jest wówczas las rozpinający.
        /// </remarks>
        public static double Lab04_Kruskal(this Graph g, out Graph mst)
        {
            // 1 pkt
            if (g.Directed)
            {
                throw new System.ArgumentException("Graf jest skierowany");
            }

            EdgesPriorityQueue edgesQueue = new EdgesMinPriorityQueue();

            g.GeneralSearchAll <EdgesQueue>(null, null, e =>
            {
                if (e.From < e.To)
                {
                    edgesQueue.Put(e);
                }
                return(true);
            }, out int cc);

            UnionFind uf = new UnionFind(g.VerticesCount);

            mst = g.IsolatedVerticesGraph();

            double weight = 0;

            while (!edgesQueue.Empty)
            {
                Edge e = edgesQueue.Get();
                if (uf.Find(e.From) != uf.Find(e.To))
                {
                    uf.Union(e.From, e.To);
                    mst.AddEdge(e);
                    weight += e.Weight;
                }
            }
            return(weight);
        }
コード例 #6
0
        /// <summary>
        /// Wyznacza minimalne drzewo rozpinające grafu algorytmem Kruskala
        /// </summary>
        /// <param name="g">Badany graf</param>
        /// <param name="mst">Wyznaczone drzewo rozpinające (parametr wyjściowy)</param>
        /// <returns>Waga minimalnego drzewa rozpinającego</returns>
        /// <remarks>
        /// Dla grafu skierowanego metoda zgłasza wyjątek <see cref="System.ArgumentException"/>.<br/>
        /// Wyznaczone drzewo reprezentowane jast jako graf bez cykli, to umożliwia jednolitą obsługę sytuacji
        /// gdy analizowany graf jest niespójny, wyzmnaczany jest wówczas las rozpinający.
        /// </remarks>
        public static int Lab04_Kruskal(this Graph g, out Graph mst)
        {
            // 1 pkt

            // wykorzystac klase UnionFind z biblioteki Graph
            if (g.Directed)
            {
                throw new System.ArgumentException("Directed graphs are not allowed");
            }
            Graph                 t  = g.IsolatedVerticesGraph();
            UnionFind             uf = new UnionFind(g.VerticesCount);
            EdgesMinPriorityQueue q  = new EdgesMinPriorityQueue();
            int TotalWeight          = 0;

            //KRUSKAL
            //for (int v = 0; v < g.VerticesCount; v++)
            //{
            //    foreach (var e in g.OutEdges(v))
            //    {
            //        q.Put(e);
            //    }
            //}

            //while (!q.Empty && t.EdgesCount < t.VerticesCount - 1)
            //{
            //    Edge e = q.Get();
            //    if (uf.Find(e.From) != uf.Find(e.To))
            //    {
            //        t.AddEdge(e);
            //        uf.Union(e.From, e.To);
            //        TotalWeight += (int)e.Weight;
            //    }
            //}

            //BORUVKA
            bool change;

            do
            {
                change = false;
                for (int i = 0; i < g.VerticesCount; i++)
                {
                    Edge MinEdge = new Edge(i, int.MaxValue, int.MaxValue);
                    bool find    = false;

                    foreach (Edge e in g.OutEdges(i))
                    {
                        if ((e.Weight < MinEdge.Weight || (e.Weight == MinEdge.Weight && e.To < MinEdge.To)) && uf.Find(e.To) != uf.Find(e.From))
                        {
                            MinEdge = e;
                            find    = true;
                        }
                    }

                    if (find)
                    {
                        q.Put(MinEdge);
                    }
                }

                while (!q.Empty)
                {
                    Edge e = q.Get();
                    if (uf.Find(e.To) != uf.Find(e.From))
                    {
                        uf.Union(e.To, e.From);
                        t.AddEdge(e);
                        TotalWeight += (int)e.Weight;
                        change       = true;
                    }
                }
            } while (change);

            mst = t;
            return(TotalWeight);
        }
コード例 #7
0
        /// <summary>
        /// Wyznacza minimalne drzewo rozpinające grafu algorytmem Boruvki
        /// </summary>
        /// <param name="g">Badany graf</param>
        /// <param name="mst">Wyznaczone drzewo rozpinające (parametr wyjściowy)</param>
        /// <returns>Waga minimalnego drzewa rozpinającego</returns>
        /// <remarks>
        /// Dla grafu skierowanego metoda zgłasza wyjątek <see cref="System.ArgumentException"/>.<br/>
        /// Wyznaczone drzewo reprezentowane jast jako graf bez cykli, to umożliwia jednolitą obsługę sytuacji
        /// gdy analizowany graf jest niespójny, wyznaczany jest wówczas las rozpinający.
        /// </remarks>
        public static int Boruvka(this IGraph g, out IGraph mst)
        {
            if (g.Directed)
            {
                throw new System.ArgumentException("Directed graphs are not allowed");
            }
            IGraph                t  = g.IsolatedVerticesGraph();
            UnionFind             uf = new UnionFind(g.VerticesCount);
            EdgesMinPriorityQueue q  = new EdgesMinPriorityQueue();
            int TotalWeight          = 0;

            bool change;

            do
            {
                change = false;
                for (int i = 0; i < g.VerticesCount; i++)
                {
                    Edge MinEdge = new Edge(i, int.MaxValue, int.MaxValue);
                    bool find    = false;

                    foreach (Edge e in g.OutEdges(i))
                    {
                        if ((e.Weight < MinEdge.Weight || (e.Weight == MinEdge.Weight && e.To < MinEdge.To)) && uf.Find(e.To) != uf.Find(e.From))
                        {
                            MinEdge = e;
                            find    = true;
                        }
                    }

                    if (find)
                    {
                        q.Put(MinEdge);
                    }
                }

                while (!q.Empty)
                {
                    Edge e = q.Get();
                    if (uf.Find(e.To) != uf.Find(e.From))
                    {
                        uf.Union(e.To, e.From);
                        t.AddEdge(e);
                        TotalWeight += e.Weight;
                        change       = true;
                    }
                }
            } while (change);
            // utworz graf mst skladajacy sie z izolowanych wierzcholkow
            // zainicjuj "poczatkowe spojne skladowe" jako pojedyncze wierzcholki (klasa UnionFind)
            // utworz pusta kolejke priorytetowa krawedzi q (klasa EdgesMinPriorityQueue)
            //
            // dopoki cos sie zmienia
            //     {
            //     dla kazdego wierzcholka
            //         {
            //         znajdz najkrotsza wychodzaca z niego krawedz prowadzaca do wierzcholka z innej spojnej skladowej (pamietaj o uwadze !)
            //         wstaw ta krawedz do kolejki priorytetowej q
            //         }
            //     dopoki kolejka q jest niepusta
            //         {
            //         pobierz element (krawedz) z kolejki q
            //         jesli krawedz laczy rozne skladowe spojne
            //             {
            //             dodaj ja do grafu mst
            //             wykonaj inne niezbedne czynnosci
            //             }
            //         }
            //     zwroc wage drzewa
            //     }
            //
            // Uwaga: jesli kilka krawedzi ma te sama wage wybierany krawedz prowadzaca do wierzcholka o najnizszym numerze

            mst = t;             // zmien to !!!
            return(TotalWeight); // zmien to !!!
        }