Aici sunt prezentate diferențele dintre versiunile selectate și versiunea curentă a paginii.
Ambele părți revizuirea anterioară Versiuni anterioare Urmatoarea versiune | Versiuni anterioare Urmatoarea versiune Ambele părți următoarea reviziune | ||
laboratoare:laborator-07 [2017/04/01 16:58] mihai.iacov [3.2 Algoritmul Bellman-Ford] |
laboratoare:laborator-07 [2017/04/01 19:34] mihai.iacov [5. Observaţii finale] |
||
---|---|---|---|
Linia 23: | Linia 23: | ||
<note important> | <note important> | ||
+ | |||
+ | ====2.3 Legătura muchii-arce: | ||
+ | <note tip> | ||
+ | Orice graf **neorientat** este echivalent cu un graf **orientat** dacă înlocuim fiecare **muchie** cu **două arce**(de acelaşi cost, câte un arc pentru fiecare sens). | ||
+ | |||
+ | Algoritmii următori pot fi folosiţi(în limita observaţiilor finale) pe grafuri orientate la fel ca pe grafuri neorientate. | ||
+ | </ | ||
+ | |||
+ | |||
===== 3.Drumul de cost minim cu sursă unică ====== | ===== 3.Drumul de cost minim cu sursă unică ====== | ||
Următorii algoritmi caută drumurile de cost minim de la **un singur nod(sursă)** la **toate celelalte noduri**. Rezultatul acestor algoritmi este un **arbore cu drumuri de cost minim**, unde: | Următorii algoritmi caută drumurile de cost minim de la **un singur nod(sursă)** la **toate celelalte noduri**. Rezultatul acestor algoritmi este un **arbore cu drumuri de cost minim**, unde: | ||
Linia 44: | Linia 53: | ||
<note tip> | <note tip> | ||
+ | <note important> | ||
+ | Pentru grafuri orientate, ne referim la vecinii la care putem ajunge printr-un arc ce pleacă din C: (C,V). | ||
+ | </ | ||
Paşii algoritmului lui Dijkstra: | Paşii algoritmului lui Dijkstra: | ||
< | < | ||
Linia 104: | Linia 116: | ||
==== 4.1 Algoritmul Floyd-Warshall ==== | ==== 4.1 Algoritmul Floyd-Warshall ==== | ||
- | ===== 5.Exiciții laborator ====== | + | Rezultatul algoritmului este o matrice N x N(unde N = |V|, numărul de noduri), iar valorea din matrice de la poziţia [i][j] va fi costul minim pentru drumul i-j. Fie această matrice numită **dist**. |
+ | |||
+ | Pentru simplitate, algoritmul numerotează nodurile de la 1 la N şi foloseşte următoarea construcţie: | ||
+ | * defineşte o funcţie costMinim(i, | ||
+ | * -pleacă din i | ||
+ | * -ajunge în j | ||
+ | * -în afară de primul şi de ultimul nod, conţine numai noduri din {1, | ||
+ | |||
+ | Algoritmul calculează costMinim(i, | ||
+ | |||
+ | <note tip> | ||
+ | Observaţii: | ||
+ | * costMin(i, | ||
+ | * costMin(i, | ||
+ | |||
+ | </ | ||
+ | |||
+ | Paşii algoritmului Floyd-Warshall: | ||
+ | |||
+ | < | ||
+ | 1. Declarăm matricile: | ||
+ | dist, matrice N x N şi o iniţializăm dist[i][j] = infinit, pentru orice i şi j | ||
+ | next, matrice N x N în care vom salva prima muchie din drumul i-j de cost minim | ||
+ | //next este necesar doar în cazul în care ne interesează muchiile folosite | ||
+ | //pasul k = 0 | ||
+ | 2. Pentru fiecare nod v | ||
+ | 1. dist[v][v] = 0; | ||
+ | 3. Pentru fiecare pereche (u,v) a.i. există muchie de la u la v | ||
+ | 1. dist[u][v] = costMuchie(u, | ||
+ | 2. next[u][v] = v; //pentru urmărirea muchiilor ce compun drumul | ||
+ | //am terminat pasul k = 0 | ||
+ | 4. Pentru fiecare pas k (de la 1 la N) | ||
+ | 1. Pentru fiecare nod i (de la 1 la N) | ||
+ | 1. Pentru fiecare nod j (de la 1 la N) | ||
+ | 1. calculăm costul nou = dist[i][k] + dist[k][j]; | ||
+ | 2. comparăm costul nou cu costul vechi = dist[i][j] | ||
+ | dacă e mai bun costul nou: | ||
+ | 1. dist[i][j] = costul nou; | ||
+ | 2. next[i][j] = next[i][k]; //pentru urmărirea muchiilor | ||
+ | altfel păstrăm costul vechi | ||
+ | </ | ||
+ | |||
+ | Pentru obţinerea nodurilor ce formează drumul de cost minim de la u la v, putem folosi următoarea secvenţă: | ||
+ | < | ||
+ | funcţie afişareDrum(u, | ||
+ | 1. dacă u == v | ||
+ | 1. print(v); STOP | ||
+ | 2. print(u); | ||
+ | 3. afişareDrum(next[u][v], | ||
+ | </ | ||
+ | |||
+ | ===== 5. Observaţii finale ====== | ||
+ | <note tip> | ||
+ | Cei 3 algoritmi funcţionează bine atunci când **toate muchiile** au **cost pozitiv**. | ||
+ | </ | ||
+ | <note warning> | ||
+ | Drumul de cost minim **NU** este bine definit atunci când există **cicluri cu cost negativ**. | ||
+ | * putem ajunge de la un nod la acelaşi nod, folosind acelaşi ciclu de oricâte ori => costMinim = -infinit); | ||
+ | * în aceste cazuri, nu putem pune problema găsirii drumurilor de cost minim. | ||
+ | |||
+ | </ | ||
+ | <note warning> | ||
+ | O **muchie cu cost negativ** este echivalentă cu **2 arce cu cost negativ** şi implică existenţa unui ciclu cu cost negativ. | ||
+ | </ | ||
+ | <note tip> | ||
+ | Algoritmii **Bellman-Ford** şi **Floyd-Warshall** pot detecta dacă un graf conţine **cicluri cu cost negativ**: | ||
+ | * Bellman-Ford: | ||
+ | * Floyd-Warshall: | ||
+ | |||
+ | </ | ||
+ | <note important> | ||
+ | Pentru algoritmul lui **Dijkstra**, | ||
+ | * Algoritmul se bazează pe ideea că, odată explorat un nod, drumul de cost minim până la acel nod a fost găsit, ceea ce **NU** este mereu corect în prezenţa unui arc cu cost negativ. | ||
+ | * De aceea, algoritmul poate produce răspunsuri **greşite** în acest caz. | ||
+ | |||
+ | </ | ||
+ | <note tip>În schimb, algoritmii **Bellman-Ford** şi **Floyd-Warshall** funcţionează pe grafurile cu **arce cu cost negativ**, atâta timp cât drumurile de cost minim sunt bine definite(**fără cicluri cu cost negativ**). | ||
+ | </ | ||
+ | |||
+ | ===== 6.Exiciții laborator ====== | ||
- | ===== 6.Referințe ====== | + | ===== 7.Referințe ====== |
- [[https:// | - [[https:// | ||
- [[https:// | - [[https:// |