Algorytm Kruskala
RNO-Wiki
Algorytm Kruskala znajduje minimalne drzewo spinające w grafie z wagami na krawędziach. Wagi mogą być właściwie dowolnymi liczbami.
Algorytm zaczyna od pustego drzewa i zachłannie dodaje do niego kolejne krawędzie. Zachłanność polega na wybieraniu krawędzi o najmniejszych wagach. W tym celu algorytm najpierw sortuje wszystkie krawędzie po ich wagach, a następnie próbuje je dodawać do drzewa, pomijając oczywiście te krawędzie, które utworzą cykl. Do tego właśnie algorytm wykorzystuje strukturę UNION FIND. Algorytm ma złożoność czasową m log(m) + n log* n.
Poniżej znajduje się implementacja algorytmu Kruskala w języku C++.
#include<algorithm> using namespace std; /* Rafał Nowak , www.rafalnowak.pl 2008.02.27 */ int tab[7000], ile[7000]; // 7000 - to liczba wszystkich elementów int Find(int a) { return (tab[a]==a) ? a : (tab[a] = Find(tab[a])); } bool Union(int a, int b) { int fa = Find(a); // szukaj reprezentanta zbioru zawierającego element 'a' int fb = Find(b); // szukaj reprezentanta zbioru zawierającego element 'b' if (fa==fb) return false; // nie trzeba nic łączyć if (ile[fa] <= ile[fb]) { ile[fb] += ile[fa]; tab[fa] = fb; } else { ile[fa] += ile[fb]; tab[fb] = fa; } return true; } pair< int,pair<int,int> > Edges[300000]; // tablica krawędzi do posortowania int main(void) { /* Na poczatku mamy n zbiorów rozłącznych : każdy ma jeden elelement {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9} */ int n, m, a,b,c,cost=0; scanf("%d %d", &n, &m); for (int i=0; i<n; i++) { tab[i] = i; // reprezentantem zbioru zawierającego element // 'i' jest np 'i' (nikt inny być nie może :-) ile[i] = 1; // jeden element; chyba jasne, co nie? } for (int i=0; i<m; i++) { scanf("%d %d %d", &a, &b, &c); a--; b--;; Edges[i] = make_pair( c, make_pair(a,b) ); } sort(Edges, Edges+m); for (int i=0; i<m; i++) if ( Union(Edges[i].second.first,Edges[i].second.second) ) { cost += Edges[i].first; // krawędz drzewa : Edges[i].second.first -- Edges[i].second.second } printf("%d\n", cost); return 0; } |
|
Algorytm Kruskala ma pewną zaletę, której nie ma Algorytm Prima-Dijkstry. Otóż algorytm ten nie musi pamiętać struktury całego grafu. Jego złożoność pamięciowa zależy tylko i wyłącznie od liczby wierzchołków.
