Sunteți pe pagina 1din 5

Algoritmul lui Dijkstra in C++ – Teoria

Grafurilor
By Matraguna Mihai Last updated mart. 9, 2018

 1

 Share

Algoritmul lui Dijkstra


Ce este si ce face acest algoritm?
Algoritmul lui Dijkstra este un algoritm foarte popular in Teoria Grafurilor. Acesta
determina lungimea cea mai scurta de la un nod de start „N” la toate celalalte noduri
ale grafului. O mica precizare foarte importanta este faptul ca algoritmul lui
Dijkstra functioneaza numai pe grafurile orientate (adica cele „cu un singur
sens”). De asemenea, fiecare muchie a grafului trebuie sa aiba atasat un cost.

Daca doresti sa determini drumul minim de la un nod X la un nod Y, si te intereseaza


doar ca numarul de noduri sa fie minim, poti atasa fiecarei muchii costul „1”. Drumul
de cost minim intre doua noduri obtinut in urma aplicarii algoritmului lui Dijkstra va
avea si numar minim de arce din moment ce toate arcele au acelasi cost.

De asemenea, algoritmul lui Dijkstra functioneaza atat pe grafuri conexe cat si pe


grafuri neconexe. In caz ca ati uitat ce este „o componenta conexa”, am explicat acest
termen in tutorialul despre parcurgerea in adancime (dfs) a unui graf.

Daca vreti sa va jucati putin, ca sa cunoasteti mai bine algoritmul, va recomand


aceasta aplicatie web.

Prezentarea generala
Algoritmul lui Dijkstra porneste de la un graf orientat si ponderat (fiecare muchie are
un cost). Dupa aceea, programatorul alege nodul de start, iar algoritmul va calcula
distanta minima de la nodul de start catre toate celalalte noduri.

Dupa executarea acestui algoritm, rezultatul va fi stocat intr-un vector „distanta” cu „N”
elemente. Unde distanta[i] va reprezenta drumul minim de la nodul nostru de start
catre nodul cu numarul i.
Problema Dijkstra – infoarena.ro
In continuare vom rezolva impreuna problema Dijkstra de pe infoarena.ro. Varianta pe
care urmeaza sa o abordam foloseste o coada de prioritati (heap-uri) pentru a obtine
punctajul maxim.

Reprezentarea grafului descris in problema


Mare atentie: nodul nostru de start este nodul numarul 1!

Algoritmul lui Dijkstra


1. Creeam un vector int D[NMax]; cu semnificatia: D[i] – distanta minima intre
nodul de start si nodul numarul i. Initial setam tot vectorul pe infinit, iar D[Start]
il vom seta pe 0.
2. Marcam toate nodurile ca fiind nevizitate. Si creeam o coada de prioritate
(priority queue / heap-uri) ce o vom folosii pentru acest algoritm. Punem nodul
de start in coada.
3. Luam nodul – cu valoarea D[nod] minima – din coada si il marcam ca vizitat.
4. Se actualizeaza distantele minime ale vecinilor nodului curent.
5. Eliminam nodul curent din coada
6. Se repeta de la punctul 3 pana cand toate nodurile sunt vizitate.

Ce face coada de prioritate / Heap-ul ? Ce rol are?


O coada de prioritate este un tip „special” de coada. Principiul este la fel, poti sa
introduci elemente in coada, sa le accesezi si sa le elimini.
Doar ca in acest caz valorile intra si ies din coada in functie de „prioritatea” pe care o
au.
Ne vom folosii de urmatoarea „prioritate”. Deoarece trebuie sa accesam tot
timpul distanta minimaa unui nod (D[i]) din coada, vom folosii aceasta conditie
drept un criteriu de extragere a nodurilor din coada.

1 struct compara
2 {
3     bool operator()(int x, int y)
4     {
5         return D[x] > D[y];
6     }
7 };
8  
9 priority_queue<int, vector<int>, compara> Coada;

In primele randuri am declarat o functie care compare distantele a doua noduri x si y.


Avem nevoie sa modificam aceasta proprietate a cozii de prioritate pentru a rezolva
problema.

priority_queue<> are 3 parametrii:

 Primul paramestru este un obiect care construieste coada. In cazul nostru sunt
numere, asa ca am scris int
 Al doilea parametru este structura in care adunam toate obiectele din coada, in
cazul nostru: un vector de int-uri
 Ultimul parametru (care este optional) este o functie ce returneaza TRUE sau
FALSE in functie de interogarile noastre

Implementarea in C++
Algoritmul lui Dijkstra in C++
C++

1 /* Tutoriale-Pe.NET - Algoritmul lui Dijkstra


2 * Link: http://tutoriale-pe.net/algoritmul-lui-dijkstra-c/
3 * Rezolvare infoarena: http://www.infoarena.ro/problema/dijkstra
4 */
5 #include    <iostream>
6 #include    <fstream>
7 #include    <queue>
8 #include    <vector>
9  
10 using namespace std;
11  
12 ifstream fin("dijkstra.in");
13 ofstream fout("dijkstra.out");
14  
15 const int NMax = 50005;
16 const int oo = (1 << 30);
17  
18 int N, M;
19 int D[NMax];
20 bool InCoada[NMax];
21  
22 vector < pair <int,int> > G[NMax];
23  
24 struct compara
25 {
26     bool operator()(int x, int y)
27     {
28         return D[x] > D[y];
29     }
30 };
31  
32 priority_queue<int, vector<int>, compara> Coada;
33  
34 void Citeste()
35 {
36     fin >> N >> M;
37     for(int i = 1; i <= M; i++)
38     {
39         int x, y, c;
40         fin >> x >> y >> c;
41         G[x].push_back(make_pair(y,c));
42     }
43 }
44  
45 void Dijkstra(int nodStart)
46 {
47     for(int i = 1; i <= N; i++)
48         D[i] = oo;
49  
50     D[nodStart]=0;
51  
52     Coada.push(nodStart);
53     InCoada[nodStart] = true;
54  
55     while(!Coada.empty())
56     {
57         int nodCurent = Coada.top();
58         Coada.pop();
59  
60         InCoada[nodCurent] = false;
61         for(size_t i = 0; i < G[nodCurent].size(); i++)
62         {
63             int Vecin = G[nodCurent][i].first;
64             int Cost = G[nodCurent][i].second;
65             if(D[nodCurent] + Cost < D[Vecin])
66             {
67                 D[Vecin] = D[nodCurent] + Cost;
68                 if(InCoada[Vecin] == false)
69                 {
70                     Coada.push(Vecin);
71                     InCoada[Vecin] = true;
72                 }
73             }
74         }
75     }
76 }
77  
78 void Afiseaza()
79 {
80     for(int i = 2; i <= N; i++)
81     {
82         if(D[i] != oo)
83             fout << D[i] << " ";
84         else
85             fout << "0 ";
86     }
87 }
88  
89 int main()
90 {
91     Citeste();
92     Dijkstra(1);
93     Afiseaza();
94 }

S-ar putea să vă placă și