Algoritmii pentru determinarea drumurilor minime au multiple aplicații practice si reprezintă clasa de algoritmi pe grafuri cel mai des utilizată. Câteva exemple de aplicații sunt:
Puteți consulta capitolele Single-Source Shortest Paths și All-Pairs Shortest Paths din Introduction to Algorithms [0] pentru mai multe definiții formale. Această secțiune sumarizează principalele notații folosite în laboratoarele de PA.- Shortest-paths problem
Cele mai uzuale notații din laboratoarele de grafuri sunt descrise în Precizări laboratoare 07-12 (ex. $n$, $m$, $adj$, $adj\_trans$, $(x, y)$, etc).
Vom adăuga alte notații în continuarea celor introduse anterior.
Costul unei muchii / edge cost: $w[u][v]$ reprezintă costul muchiei de la nodul $u$ la nodul $v$.
Drum / Path: $p = (v_1, v_2, ..., v_k)$ este un drum în graful $G = (V, E)$, dacă pentru oricare $i = 1:k - 1$, există muchia $(v_i, v_{i+1})$.
Costul unui drum / path cost: $w(p) = \sum_{i=1:k-1} {w[v_i][v_{i+1}]}$ - costul unui drum $p$ este suma costurior muchiilor care îl compun.
Shortest-paths problem / problema drumurilor minime: Dat fiind un graf $G = (V, E)$, dorim să aflăm drumul de cost / lungime minimă între anumite noduri din graf.
Sursă unică / single-source shortest-paths problem: Se dă un graf $G = (V, E)$ și un nod special $source$, considerat sursă. Se cere calculul distanței de la sursa source la toate nodurile din graf. Formal: $d[v] = distanța\ de\ la\ sursa\ \textbf{source}\ la\ nodul\ \textbf{v}$.
Destinație unică / single-source shortest-paths problem: Se dă un graf $G = (V, E)$ și un nod special $destination$, considerat destinație. Se cere calculul distanței de la fiecare nod la nodul destination. Putem reduce această problema la cea de sursă unică (pentru graf orientat, trebuie să folosim graful transpus).
Pereche unică / single-pair shortest-path problem: Se dă un graf $G = (V, E)$. Se cere calculul drumului minim între 2 noduri fixate $u$ și $v$. Observăm că din nou putem reduce problem la sursă unică, alegând pe $u$ sau $v$ drept sursă.
Surse / destinații multiple / all-pairs shortest-paths problem:: Se dă un graf $G = (V, E)$. Se cere calculul drumului minim între oricare 2 noduri $u$ și $v$. Formal: $d[u][v] = distanța\ de\ la\ nodul\ \textbf{u}\ la\ nodul\ \textbf{v}$.
Relaxarea unei muchii / edge relaxation: A relaxa o muchie $(u, v)$ constă în a testa dacă se poate reduce distanța / costul drumului de la sursa source până la nodul v, trecând prin nodul intermediar $u$ și apoi circuland pe muchia $(u, v)$.
Toți algoritmii pentru topologii generale prezentați în laboratoarele 09 și 10 se bazează pe relaxare pentru a determina drumul minim.
O să observăm că toți algoritmii studiați produc 2 rezultate: $d$ (distanțele față de sursă) și $p$ (vectorul de părinți, folosit pentru reconstituirea drumurilor).
În această secțiune prezentăm procedura de reconstruire a drumului, pornind de la destinație către sursă, apoi inversând la final șirul de noduri obținut. Această metoda este independentă de algoritmul cu care vectorul de părinți p a fost calculat!
// rebuild path from source to destination using parents vector p // (previously computed with a shortest-paths algorithm) // // source = the source for the computing distances // destination = the destination node // p[node] = parent of node on the shortest path from source to node RebuildPath(source, destination, p) { // STEP 0: Create an empty path. path = []; // STEP 1: Add nodes one by one, from destination to source going up on parents! // (source, ..., p[destination], destination) while (source != destination) { path.push_back(destination); destination = p[destination]; } // STEP 1.1: Also add the source. path.push_back(source); // STEP 2: Reverse to actually get path (source, ..., destination). reverse(path); return path; } // Usage example: // * run algorithm for computing shortests-paths d, p = RunShortestPathsAlgorithm(source, G=(nodes, edges)) // * call rebuikd path = RebuildPath(source, destination, p)
Analog se reconstitue drumul și dacă suntem pe cazul cu surse multiple, destinații multiple, unde tabloul $p$ este o matrice, iar atunci când cautăm un drum care începe cu nodul $source$, folosim doar elementele de pe linia $p[source]$.
Vom menționa câteva cazuri particulare de topologii de grafuri unde putem obține soluție optimă pentru shortest-paths problem cu noțiunile învățate anterior, nefiind necesar să folosim algoritmi mai complecși, pe care îi vom studia în continuare pentru topologii generale.
Dacă avem un graf fără costuri sau cu toate costurile egale, o soluție optimă va folosi BFS.
Dacă avem un arbore (graf neorientat acicllic), o soluție optimă va folosi DFS.
Folosind diferite preprocesări, putem calcula distanța între oricare două noduri în $O(1)$.
Daca avem un DAG (graf orientat aciclic), o soluție optimă va folosi Topological Sort.
Mai există o varianta a problemei pe care dorim să o menționăm. Avem k surse (sau destinații), unde k « n (k mult mai mic decât n - de exemplu, $k = 10$ constant) și ne interesează să găsim distanța pentru fiecare nod din graf către cea mai apropiată sursă.
O abordare naivă ar rula de k ori un algorthm de drumuri minime (de exemplu, Dijkstra) și pentru fiecare nod ar reține minimul dintre cele k distanțe calculate pentru un nod. Complexitatea este $O(k * complexitate\_algoritm$).
O optimizare pe care o putem facem, este să adaugăm un nod fictiv $S$ și să îl unim cu fiecare dintre cele k noduri cu muchie de cost 0. În noul graf format, dacă vom rula un algoritm să găsim toate distanțele de la nodul S la celelalte noduri din graf, rezolvăm și problema inițială.
Dacă alegem să folosim Dijkstra, putem să nu modificăm graful. Dacă băgăm cele k surse în heap în etapa de inițializare, efectul este ca și cum s-ar fi scos nodul S și s-au relaxat toate muchiile care pornesc din acesta.
[0] Chapters Single-Source Shortest Paths / All-Pairs Shortest Paths, “Introduction to Algorithms”, Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest and Clifford Stein.