Algoritmul lui Kruskal este un algoritm de tip greedy care gsete arborele parial
de cost minim pentru un graf conex ponderat.
Termeni utilizai: - Graf conex = graf ntre care oricare dou vrfuri ale acestuia exist cel puin un drum. - Graf ponderat = graf n care fiecrei muchii i este asociat o valoare numit cost. Dac graful nu este conex, atunci algoritmul va gsi o pdure parial de cost minim. - Pdure = graf n care componentele conexe sunt arbori. Pasul 1: ordoneaz cresctor lista muchiilor n funcie de costuri Pasul 2: creeaz un arbore, verificnd la fiecare pas dac muchia adugat nu nchide un ciclu (verific dac capetele muchiei nu aparin aceleiai componente conexe) Pasul 3: construiete arborele parial de cost minim
La sfritul algoritmului, pdurea are doar o component care reprezint un arbore parial de cost minim al grafului. Pentru a rspunde rapid la ntrebrile de tipul sunt n acelai arbore nodurile x i y? avem nevoie de o structur de date numit Pduri de mulimi disjuncte.
Aceasta reine o partiionare a mulimii ,1,.,n- n mai multe mulimi disjuncte, permite unirea a dou mulimi i rspunde la ntrebri de forma care este mulimea din care face parte x.
Structura se ntreine ca o pdure de arbori n care fiecare arbore reprezint o mulime, aadar, printr-un vector de tai.
Unirea a dou mulimi se realizeaz prin unirea celor dou rdcini ale arborilor. Exemplu: pentru cele dou rdcini x i y, T[tata(y)] = tata(x) )
Determinarea mulimii din care face parte x se face parcurgnd lanul de la nodul x la tata.
Aceast implementare are o complexitate de N pai per ntrebare. Pentru a reduce complexitatea, la fiecare iteraie a funciei tata, schimbm T*x+ cu valoarea returnat de aceast funcie.
Alte funcii utile folosite: - sortarea predefinit: sort(primul_elem,ultimul_elem,criteriu_de_sortare)
struct Muchie{int x, y, c;}; int T[50], n, m, nr; Muchie edge[50], sol[50];
bool comp(Muchie a, Muchie b) //criteriul de comparare { return a.c<b.c; } int tata(int x) //determinarea mulimii din care face parte x { if (x == T[x]) return x; return tata(T[x]); } void merge(int x, int y) //funcia de unire a dou mulimi prin unirea rdcinilor lor (x i y) { x=tata(x); y=tata(y); if (x != y) T[y] = x; } void kruskal() { sort(edge+1, edge+m+1,comp); // sortarea cresctoare n funcie de costuri int C = 0; // variabila ce va reine costul total al pdurii finale obinute for(int i=1;i<=n;i++) // iniializarea vectorului de tai cu i; iniial considerm fiecare nod T[i]=i; // aparinnd mulimii format doar din el nsui for (int i=1;i<=m;i++) if(tata(edge[i].x)!=tata(edge[i].y)) { merge(edge[i].x,edge[i].y); // unirea celor dou mulimi dac rdcinile lor nu se gsesc n sol[++nr]=edge[i]; // aceeai component conex i construcia vectorului soluie C+=edge[i].c; } out<<C<<"\n"<<nr<<"\n"; for (int i=1;i<=nr;i++) out<<sol[i].x<<" "<<sol[i].y<<"\n"; } int main(){ in>>n>>m; for (int i=1;i<=m;i++) in>>edge[i].x>>edge[i].y>>edge[i].c; kruskal(); return 0; }