//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ć }
// 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); }
//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); }
//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); }
/// <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); }
/// <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); }
/// <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 !!! }