Sunteți pe pagina 1din 22

6.4.

2 Algoritmul lui Kruskal


In timp ce algoritmul Dijkstra-Prim a inceput cu un nod particular si a construit MST-ul, algoritmul Kruskal se concentreaza in schimb pe puntile grafului. In acest algoritm, incepem cu un arbore fara ramuri si adaugam punti astfel incat sa creasca inraurirea pana cand toate nodurile sunt conectate la graf. Daca ramanem fara punti inainte ca toate nodurile sa fie conectate graful original nu va fi conectat iar rezultatul pe care il aveam de generat este MST-ul ale fiecarei componente conectate la graful original. Incepem cu figura 6.6A cu acelasi graf pe care l-am folosit in algoritmul Dijkstra-Prim. In acest caz mai intai adaugam puntea cu cea mai mica inraurire care este unul dintre nodurile D si F dand rezultatul partial in figura 6.6B. Figura 6.6A : Graful Original

Figura 6.6B : Prima punte adaugata

Puntea cu inraurirea 2 este apoi adaugata (Figura 6.6C) intre nodurile A si B, si apoi puntea cu inraurirea 3 este adaugata rezultand Figura 6.6D. Figura 6.6C : A doua punte adaugata

Figura 6.6D : A treia punte adaugata

Puntile cu inrauririle 4 si 5 sunt apoi adaugata la rezultatul nostru dupa cum putem vedea in Figura 6.6E si 6.6F. Singurul nod care este inca neconectat este G. Urmatoarele punti considerate vor fi cele care au inraurirea 6. Figura 6.6E : A patra punte adaugata

Figura 6.6F : A cincea punte adaugata

Dintre cele 4 punti cu inraurirea 6, 2 sunt inlaturate deoarece ele vor forma un ciclu cu punti care fac parte deja din MST. Puntea dintre nodurile C si F va forma un ciclu care include nodul A si puntea dintre nodul B si D va forma un ciclu care include nodurile A si F. Celelalte noduri sunt ambele alternative bune si depind de cea aleasa, luam MST ori in figura 6.6G ori in 6.6H. Figura 6.6G : MST

Figura 6.6H : O alternativa de MST

Algoritmul general care il va indeplini este(unde E reprezinta numarul de punti):


sorteaza puntile descrescator dupa importanta initializeaza structura partitionata edgeCount=1 includedCount=0 while edgeCount<=E and includedCount<=N-1 do parent1=FindRoot(edge[edgeCount].start) parent2=Findroot(edge[edgeCount].end) if parent1!=parent2 then add edge[edgeCount] to spanning tree includedCount=includedCount+1 Union(parent1,parent2) end if edgeCount=edgeCount+1 end while

Bucla noastra principala va continua pana cand variabila edgeCount va indica ca am parcurs toate puntile sau variabila includedCount indica faptul ca am adaugat destule punti pentru a creea posibilul arbore.Ar trbui sa sesizati ca daca avem N noduri in graf arboreal va avea cu o punte mai putina decat numarul de noduri. In interioul buclei mai intai gasim parintii celor doua noduri,parinti care sunt conectati de urmatoarea punte dupa cum urmeaza.Daca acele noduri sunt impartite cu diferite surse adaugand o punte intre ele nu se va realiza un ciclu,deci aceasta punte curenta poate fi adaugata la MST si acele doua piese pot fi alaturate astfel incat sa aiba acum aceeasi sursa.Detaliile lui FindRoot si ale rutinelor Union vor fi date in sectiunea 6.7. Complexitatea acestui algoritm va fi complexitatea algoritmului sortat si folosit deoarece bucla while are o legatura liniara cu numarul de punti.Acest lucru reprezinta complexitatea algoritmului MST al lui Kruskal. 6.4.3 Exercitii 1.Gasiti MST folosind algoritmul Dijkstra-Prim pentru urmatoare grafuri pornind de la nodul A.Aratati pasii:

a. b.

c.

d.

2.Gaseste MST-ul folosind algoritmul Kruskal pentru grafurile de la punctul 1.Arati toti pasii. 3.Faceti o analiza al algoritmului MST Dijkstra-Prim tinand cont de cate ori este considerata o punte pentru nodurile adaugate la margine, pentru updatarea puntilor ale nodurilor de la margine sau ia nodul pentru a-l muta de la margine la MST. 4. Demonstreaza ca daca acolo este o punte cu o inraurire mai mica decat toate celelalte punti, acea punte va fi parte din fiecare MST. 5. Demonstreaza ca daca un graf conect are toate inrauririle puntii distincte ( in alte cuvinte 2 noduri nu pot avea aceea inraurire ), acolo este doar un singur MST. 6. Demonstreaza ca daca este tot timpul, niciodata sau cateodata adevarat ca ordinea in care nodurile sunt adaugate in MST de algoritmul lui Dijkstra-Prim sunt in aceeasi ordine in care ele sunt intalnite intr-o prima latime transversala. 7. Demonstrati ca daca este tot timpul, niciodata sau cateodata adevarat ca ordinea in care nodurile sunt adaugate in MST de algoritmul Dijkstra- Prim este acelasi cu ordinea in care ele sunt intalnite in prima inaltime transversala. S-ar parea ca putem folosi algoritmul MST pentru a diviza cateva punti si apoi doar sa privim drumul dintre nodurile arborelui. Din pacate acest lucru nu va produce intotdeauna cea mai scurta cale. Tineti minte ca algoritmul MST incearca sa gaseasca in general un total care este cel mai mic, deci va arata pentru cea mai mica, posibila importanta. De exemplu, ganditi-va la un graf care este de forma circulara. In alte cuvinte primul nod este conectat la al doilea, care este conectat la al treilea si asa mai departe pana cand ultimul nod este conectat la primul. Graful este doar un inel unde fiecare nod este conectat la 2 noduri de o parte si de alta a sa. De exemplu, figura 6.7 ne arata un exemplu de graf cu 6 noduri. Tineti minte ca importanta tuturor puntilor este unu exceptand puntea dintre nodul A si nodul B care are o importanta de 2. Algoritmul MST va selecta toate puntile de importanta unu si va intrerupe legatura cu puntea de importanta 2. dar aceste intelesuri ca drumul dintre nodul A si nodul B in MST ( figura 6.7B ) trebuie sa treaca prin toate celelalte noduri printr-un drum de lungime de 5. este clar ca nu este cel mai scurt drum deoarece puteti observa in figura 6.7A ca acolo este un drum direct intre nodul A si nodul B care are lungimea 2. Figura 6.7A : Un graf de tip inel

Figura 6.7B : MST

6.5.1 ALGORITMUL DIJKSTRAS Algoritmul MST nu va gasi cel mai scurt drum deoarece este un algoritm pretentios care considera importanta unei punti la fiecare iteratie. Daca modificam algoritmul astfel incat sa aleaga puntea de la margine care este parte a celui mai scurt drum complet de la inceputul nodului, vom obtine rezultatul dorit. Mai exact, algoritmul nostru incepe:
selecteaza un nod de inceput construieste marginea initiala de la nodurile conectate la nodul de inceput cat timp nu suntem la nodul destinatie executa alege marginea nodului cu cel mai scurt drum la nodul de inceput adauga acel nod si puntile aferente lui actualizeaza marginea cu: adaugand noduri la marginea conectata la noul nod pentru fiecare nod din margine executa actualizeaza puntea sa la una conectata la arbore la cel mai scurt drum de la nodul de inceput end for end while

Figura 6.8 ne arata un exemplu de executie al acestui algoritm. Incepem cu acelasi graf pe care l-am utilizat la algoritmul MST ( reprodus aici in figura 6.8A ) si ne vom uita pentru cel mai scurt drum incepand de la nodul A si sfarsind cu nodul G. Figura 6.8A : Graful original

Figura 6.8B : Cel mai scurt drum spre nodul B

Incepand drumul nostru de la nodul A avem de luat in considera 4 posibile punti. Dintre toate 4 AB este cel mai scurt.

Nodul B este adaugat la drumul nostru cel mai scurt ( figura 6.8C ) si acum cautam sa actualizam drumurile. Nodul E si G pot fi acum incluse in garbore, deci sunt adaugate. De asemenea trebuie privit nodul D si comparat drumul sau direct spre nodul A de lungime 7 cu drumul care trece prin nodul B care are lungime 8. Deoarece drumul direct este mai scurt punte nodului D nu sufera modificari. Privind laoptiuni observam ca drumul de la nodul A la nodul C este de lungime 4 si este cel mai scurt. Puntea BE este mai scurta, dar acum consideram intregul drum de la nodul A deci lungimea drumului la nodul E este 5. Figura 6.8C : Drumul de lungime 4 la nodul C este cel mai scurt dintre optiuni

Nodul C este adaugat la cel mai scurt drum al arborelui ( figura 6.8D ). Examinand graful observam ca putem ajunge la nodul F trecand prin nodul C dar lungimea totala a drumului este 10 care este mai lunga decat drumul curent la nodul F deci nu sufera modificari. Figura 6.8D : Drumul de lungime 5 fie catre nodul E sau nodul F este cel mai scurt

Fiind data situatia din Figura 6.8D, putem alege fie drumul de la nodul A spre nodul F fie drumul de la nodul A la nodul E care trece prin nodul B, deoarece ele au ambele aceeasi lungime 5. Cel ales pe parcursul desfasurarii executiei programului, va fi intretinut de modul in care sunt stocate datele. Pentru scopurile noastre cand prezentam o optiune, vom selecta nodul care este alfabetic mai mic ( figura 6.8E ). Deoarece adaugarea nodului E la graf nu va schimba nimic la alte conexiuni acum vom alege nodul F rezultand figura 6.8F. Trebuie sa observam ca, desi selectia nodului F a schimbat puntea spre nodul D, daca am fi ales mai intai nodul F am fi trebuit sa alegem nodul E apoi. Figura 6.8E : Celalalt drum de lungime 5 catre nodul F

Figura 6.8F : Drumul de lungime 6 catre nodul D este mai scurt decat drumul spre nodul G

In figura 6.8F trebuie sa ne fie clar ca drumul catre nodul D este mai scurt decat drumul spre nodul G. Alegand nodul D ( figura 6.8G ), si apoi nodul G este ultimul care trebuie adaugat, oferindu-ne ultimul drum de lungime minima al arborelui ( figura 6.8H ). Cel mai scurt drum de la nodul A la nodul G are lungimea 10. Daca va intoarceti la figura 6.5F, veti observa alt exemplu de MST care nu are cel mai scurt drum, deoarece aceasta figura are drumul de la nodul A la nodul G de lungime 11. Figura 6.8G : Drumul catre nodul G este singurul ramas

Figura 6.8H : Cel mai scurt si complet drum al arborelui incepe de la nodul A

In exemplul din figura 6.8 avem cel mai scurt si complet drum al arborelui al nodului A deoarece nodul nostru de destinatie a fost ultimul care a fost adaugat. Daca am fi ajuns la nodul G mai devreme, algoritmul s-ar fi oprit la acel punct. Acolo sunt aplicatii unde ar trebui sa fim interesati de cel mai scurt drum de la un nod la oricare alt nod. De exemplu, daca avem o mica retea de calculatoare care are o rata stabila de transmisie inte noduri, putem calcula cel mai scurt drum la oricare alt nod pentru fiecare calculator. Apoi cand un mesaj trebuie sa fie trimis nu trebuie sa facem altceva decat sa accesam drumul predeterminat dar si cel mai scurt al tablei noastre pentru a gasi cea mai rapida cale de a trimite mesajul. 6.5.2 EXERCITII

1. Executa algoritmul drumul cel mai scurt din urmatoarele grafuri incepand cu nodul A pentru a crea in intregime cel mai scurt drum al arborelui pentru fiecare. Numara cate punti se formeaza in proces ( daca treci printr-o anumita punte de mai multe ori, numar-o de fiecare data). a.

b.

c.

d.

2. Schimba algoritmul din aceasta sectiune astfel incat sa determine eficient cel mai scurt drum de la nodul de start la fiecare nod al grafului, in loc de o destinatie anume. 3. Fa o analiza in aceasta sectiune al algoritmului drumul cel mai scurt numarand de cate ori o punte este verificata pentru noduri adaugate marginii, pentru actualizarea puntilor la nodurile marginii, sau pentru a a muta nodul e la margine la MST. 4. Demonstreaza ca prima ampla traversa realizeaza cel mai scurt drum al arborelui pentru un graf fara importanta. 5. Demonstreaza ca daca este tot timpul, niciodata sau cateodata adevarat ca ordinea in care nodurile sunt adaugate la cel mai scurt drum al arborelui este aceeasi cu ordinea in care nodurile se gasesc in ampla prima traversa. 6. Demonstreaza ca daca este tot timpul, niciodata sau cateodata adevarat ca ordinea in care nodurile sunt adaugate la cel mai scurt drum al arborelui este aceeasi cu ordinea in care nodurile se gasesc in prima traversa de importanta majora. 6.6 ALGORITM PENTRU COMPONENTE BICONECTE

O componenta biconecta a unui graf este un set de 3 sau mai multe noduri pentru care exista cel putin 2 rumuri intre fiecare nod. O componenta biconecta poate deasemenea sa aiba doar 2 noduri si o singura punte de legatura. O componenta biconecta este o parte robusta a unui graf deoarece daca un nod si puntile sale inlaturate din graf toate celelalte noduri din componenta biconecta pot fi legate la altele . Graful din figura 6.9 ne arata un graf conect care are 3 componente biconecte. Prima componenta biconecta are nodurile etichetate cu A, B si C al doilea are nodurile etichetate cu D, E , F, G si H, iar al treilea are nodurile H si I. Figura 6.9 : Un graf conect cu 2 componente biconecte

Determinand componentele biconecte ale unei retele inseamna a ne indica cat de stabila poate fi reteaua in conditii precare. Deci daca toate calculatoarele din retea fac parte dintr-o componenta biconecta dintr-un din graful asociat retelei constientizam ca reteaua va continua sa functioneze pana cand unul dintre calculatoare va iesi din functiune. In anexele liniilor aeriene componenta biconecta a grafului a anexelor zborului ne indica daca pasagerii pot fi reprogramati pe alta ruta cand un aeroport este inchis datorita instabilitatii vremii. Un punct principal dintr-un graf conect este un nod care daca il inlaturam cauzeaza o deconectare a grafului. Punctele principale ale grafului sunt nodurile impartite intre 2 componente biconecte. Nodurile D si H din figura 6.9 sunt puncte principale. Identificarea punctelor principale si determinarea punctelor biconecte se afla intr-o stransa legatura. Putem identifica punctele principale printr-o maniera mai neobisnuita inlaturand un nod la un moment dat si folosind una dintre metodele noastre traverse pentru a observa daca nodurile noastre sunt inca conectate. Daca se intampla acest lucru, nodul pe care l-am inlaturat nu este un punct principal,

iar in celalalt caz este punct principal. Aceasta inseamna ca va trebui sa executam N traversii la un graf cu N noduri. Acest proces va fi O(N^2). Pastrand o parte din informatia suplimentara cat timp parcurgem graful, putem identifica punctele principale si componentele biconecte la o parcurgere. Ganditi-va la drumurile din grafuri din figura 6.9 care incep cu nodul F. Ar trebui observat ca nu conteaza in ce ordine vizitam nodurile, drumurile de la nodul F la nodul A , B si C trecand prin nodul D. Acest lucru inseamna ca nodul D este nod principal si ca subgraful care contine nodurile A, B, C si D este o componenta biconecta. Algoritmul nostru se bazeaza pe cautarea in adancime. Ne vom intoarce la sectiune 6.3.1 unde am spus ca o cautare in adancime va urma puntile din graf pana cand un sfarsit mortal va aparea cand nodul in cauza nu are noduri adiacente nevizitate. Cand intampinam un capat de drum vom reveni la inceput dar acum algoritmul nostru va returna informatia despre cat de performanta este cautarea in adancime pana cand ajunge la capatul de drum. Aceste punti de intoarcere din cautarea din arbore indica un ciclu de intoarcere in graf. Toate nodurile dintr-un ciclu trebuie sa faca parte din aceeasi componenta biconecta. Locatia puntii de intoarcere ne indica cat de departe trebuie sa ne intoarcem inapoi in arborele nostru inainte sa ne facem griji in vederea gasirii unui punct principal. Pentru a indeplini acest algoritm vom retine numarul de noduri ale grafului pe care le-am vizitat.Fiecarui nod ii va fi atribuit un numar de index care va indica cand acesta este vizitat.In alte cuvinte,primul nod vizitat va fi numerotat cu 1,al doilea va fi numerotat cu 2 si asa mai departe.Cand vom ajunge la un capat de drum vom privi la toate nodurile adiacente(exceptie facand nodul pe care l-am vizitat ultima data),vom returna indexul nodului de la capatul de drum.Cand ne vom intoarce la un nod care nu este radacina arborelui vom compara valoarea ultimului index care a fost returnata.Daca aceea valoare este mai mare sau egala decat valoarea indexului nodului curent subarborele pe care numai ce l-am vizitat(fara nici o componenta biconecta gasita)este o componenta biconecta.Fiecare nod intern al primei cautari in adancime in arbore va returna cea mai mica valoare dintre indicii nodurilor adiacente si orice indice anterior. Cum va functiona acest proces in graful nostru din figura 6.9?Daca incepem de la nodul F ii va fi atasat valoarea indexata 1.Ne deplasam spre nodul D(index 2)apoi nodul B(index 3),A(index 4) si C (index 5).Nodul C este capat de drum si avem punti inapoi catre nodurile A,B si D.Indexul

nodului D este cel mai mic deci valoare 2 va fi returnata nodului A ca index de intoarecere.Nodul A nu este un punct principal deoarece valoare 2 este mai mica decat indexul nodului A . Valoarea 2 este de departe cea mai mica si este deasemenea la nodul B. Acest algoritm continua pana cand ne intoarce la nodul D unde vom gasi ca indexul de intoarcere returnat este acelasi ca si indexul nodului D, deci nodurile A, B, C si D formeaza o componenta biconecta. Ne intoarcem la radacina arborelui cautat la nodul F si apoi ne indreptam spre nodul E ( index 6), urmat de nodul G ( index 7), si nodul H ( index 8). Apoi ne deplasam spre nodul I ( index 9), si deoarece este un capat de drum fara noduri adiacente inafara de H, returnam indexul sau ca si index de intoarcere. Cand nodul H primeste o valoare de 9 de la nodul I care este mai mare decat indexul nodului H, gasim alta componenta biconecta cu nodurile H si I. Nodul H are acum valorile 1 ( puntea de intoarcere la F ), 9 ( returnata de la nodul I), si 8 ( indexul nodului H ), returnand cea mai mica dintre acestea la nodul G si apoi la nodul F. Aceasta valoare este apoi returnata de nodul E la radacina nodului, si deoarece toate nodurile au fost vizitate tot ce ramane ( nodurile D, E, F, G si H), va fi cuprins in ultima componenta biconecta. In figura 6.10 observam rezultatul acestui proces, si din aceasta putem observa ca punctele principale din graful original sunt nodurile D si H, care sunt singurele noduri care apar in 2 componente separate. Figura 6.10 : Componentele biconecte ale grafului din figura 6.9

6.6.1 EXERCITII 1. Determina componentele biconecte ale urmatoarelor grafuri : a.

b.

c.

d.

2. Scrie un algoritm care determina componentele biconecte ale unui graf utilizand o matrice de adiacenta. 3. Scrie un algoritm care determina componentele biconecte ale unui graf utilizand o lista de adiacenta. 6.7 SETURILE PARTITIONATE

Un numar de algoritmi trebuie sa mentina un set de valori ca si o colectie de seturi partitionate cu abilitatea de a le combina intre ele. Capabilitatea setului inerent al limbajelor de programare moderna pot fi folosite, dar in acel set nu este nimic care garanteaza ca seturile disjuncte vor functiona corect. In plus nu toate limbajele de programare au aceste seturi de capabilitati. Aceasta sectiune ne va arata o metoda de implementare a acestui set partitionat utilizand dispunerile. Am observat o utilitate a acestei capabilitati in algoritmul nostru pentru algoritmul MST al lui Kruskal. Incepem cu o aranjare numita Parent, care are o locatie pentru fiecare al setului cu care lucram. Initializam toate elementele cu -1 ceea ce reprezinta ca fiecare este radacina unei partitii ( negative) si ca partitia are un element in ea ( elementul 1). Ca lucrurile sa progreseze, daca cateva elemente din radacina partitiei cu 7 elemente este valoare in aranjarea Parent , va fi 7. Cum elementele au fost adaugate intr-o partitie, valoarea lor in aranjarea Parent va fi setata de radacina partitiei pe care ele au adaugat-o. De exemplu, daca elementul 5 este adaugat de o partitie inradacinata de elementul 8, a 5 locatie a aranjarii Parent va avea 8 inmagazinari in el, si a 8 locatie va avea valorile sale negative incrementate pentru a indica ca acolo este una sau mai multe valori in acea partitie. Elementele arajarii Parent vor avea doar imediata origine din partitie ca si valoarea lor deoarece in momentul in care 2 partitii sunt combinate, doar intrarile radacinii ale aranjarii vor fi schimbate. Considerand partitionarea din figura 6.11 observam ca acolo sunt 3 partitii cu radacinile 5, 6 si 11. Aceste locatii aranjate au valori negative indicand numarul de elemente din aceste partitii. Fiecare din alte locatii are valoarea imediata a sursei. Daca acum alaturam partitiile cu radacinile 6 si 11 putem schimba Parent [11] pentru a avea valoarea 6, este noua radacina, si vom putea schimba Parent [6] sa fie -5 reprezentand de fapt ca aceasta partitie are 5 elemente.

Figura 6.11 : O partitie cu numerele de la 1-12 si aranjarea Parent asociata ei

Algoritmii pentru realizarea acestei structuri partitionate


InitializePartition ( N ) N numarul de elemente din set For i=1 to N do Parent[i]=-1 End do

Dupa cum am spus, rutina de initializare doar seteaza fiecare locatie al aranjarii Parent la -1 pentru a indica fiecare valuare este in propria partite si fiecare partite are marimea 1.
Union ( i,j) i,j the partitions to join toghether totalElements = Parent[i] + Parent [j] if Parent[i]>=Parent[j] then Parent[i]=j Parent[j]=totalElements Else Parent[j]=i Parent[i]=totalElements End if

Functia Union este responsabila pentru contopirea a 2 partitii. Incepe prin calcularea numarului total de elemente care vor fi in partitia rezultata. Apoi adauga partitia mai mica la cea mai mare. Tineti minte ca marimile partitiei sun retinute ca numere negative, astfel incat clausa then sa adauge partitia i la partitia mai mare j, si apoi clausa else sa adauga partitia j la partitia mai mare i.
FindRoot ( s ) S elementul a carui radacina dorim

Result = s While Parent [ result] > 0 do Result = Parent [ result] End while Return result

Rutina FindRoot incepe la Parent[s], care este locatia sursei elementului s. Daca aceasta valoare este negativa, inseamna ca s este radacina unei partitii deci rezultatul lui s este returnat. Daca totusi s nu este o radacina actualizam resultatul astfel incat sa fie sursa lui s si cautam sa observam daca aceasta este radacina partitiei. Vom continua sa lucram prin aceasta metoda pana cand ajungem la radacina. O imbunatatire eficienta neinclusa aici va urmari mai tarziu acest drum inca odata va actualiza toate intrarile de-a lungul punctului cu legatura directa la radacina. Acest proces va dura mai mult timp dar incercarile viitoare de a gasi o radacina pentru aceste elemente actualizate vor decurge mai repede. 6.8 EXERCITII DE PROGRAMARE

Pentru aceste probleme va trebui sa generati grafuri complete cu n noduri. Este cel mai usor sa utilizati matricea de adiacenta deoarece trebuie doar sa umpleti fiecare intrare exceptand elementele de pe diagonala principala care trebuie sa fie 0. Veti lucra cu grafuri neorientate deci va trebui sa fiti atenti ca AdjMat [i,j] sa fie egal cu AdjMat [j,i]. Aceste probleme cer sa comparati 2 arbori sau drumurile. Acest lucru va fi usor daca va asigurati ca puntile implicate sunt listate cu cele mai mici etichete posibile deoarece aceste probleme functioneaza cu grafurile neorientate. Apoi puteti sorta puntile bazate pe nodurile lor. Daca 2 MST-uri sau drumuri sunt la fel cele 2 liste sortate trebuie sa se potriveasca exact. 1. Generati un graf complet neorientat cu 50 de noduri. Porniti Algoritmul MST Dijkstra-Prim incepand la fiecare dintre noduri si determina care MST-uri diferite ati gasit. Executati acest proces de 4 ori pentru valori diferite ale puntii ( 10,25,50,100). Elaboreaza o concluzie despre rezultatele voaste explicand ce ai descoperit. Daca faceti acest lucru pentru mai multe grafuri rezultatul va fi mult mai plauzibil. 2. Generati un graf complet neorientat cu 50 de noduri. Porniti algoritmul MST Kruskal. Daca aveti de a face cu 2 punti de aceeasi importanta alege la intamplare una dintre ele. Genereati 10 MST-uri pentru fiecare graf si observati cate sunt unice. Deoarece ati facut alegerea la intamplare, daca acolo sunt multiple MST-uri bazate pe aceste alegeri trebuie sa le gasiti. Executati acest proces de 4 ori pentru valori diferite ale

puntii ( 10,25,50,100). Scrie o concluzie despre rezultatele obtinute si o explicatie la ceea ce ai gasit. Daca faceti acest lucru pentru mai multe grafuri rezultatul va fi mult mai plauzibil. 3. Generati un graf complet neorientat cu 50 de noduri pentru fiecare pereche de noduri A si B, verificati daca cel mai scurt drum generat de la A la B este egal cu cel mai scurt drum generat de la B la A si noteaza de cate ori ele sunt diferite. Executati acest proces de 4 ori pentru valori diferite ale puntii ( 10,25,50,100). Scrie o concluzie despre rezultatele obtinute si o explicatie la ceea ce ai gasit. Daca faceti acest lucru pentru mai multe grafuri rezultatul va fi mult mai plauzibil. 4.Scrieti un program care va genera un graf complet neorientat si apoi utilizati algoritmii Dijkstra- Prim si MST Kruskal. Trebuie sa numarati si sa aveti in vedere de cate ori fiecare algoritm trece pe fiecare punte. In alte cuvinte numara de fiecare data de cate ori este accesata matricea de adiacenta. Formati aceste grafuri cu 10,25,50,100 de noduri si apoi scrieti o concluzie comparand eficientele relative ale celor 2 algoritmi . Pentru a obtine rezultate mult mai corecte trebuie sa generati si sa testati mai multe grafuri aleatorii de fiecare dimensiune.