Sunteți pe pagina 1din 102

Modulul 2.

Parcurgeri de grafuri

Cuprins
Introducere .................................................................................................................... 20
Obiectivele modului ...................................................................................................... 20
U1. Parcurgerea generică ............................................................................................. 21
U2. Parcurgerea în lăţime ............................................................................................. 33
U3. Parcurgerea în adâncime ........................................................................................ 43
U4. Aplicaţii ale parcurgerilor ...................................................................................... 56

Introducere
În acest modul ne vom ocupa de problema parcurgerii unui digraf. Acestă
problemă constă în determinarea tuturor nodurilor accesibile dintr-un nod dat,
numit nod sursă. Problema parcurgerii unui graf poate apărea ca problemă de sine
stătătoare, dar şi ca subproblemă a unei probleme mai complexe.
Vom prezenta mai întâi parcurgerea generică, iar apoi cele mai cunoscute
implementări ale acesteia: parcurgerea în lăţime şi parcurgerea în adâncime. În
finalul modulului, ne vom îndrepta atenţia asupra următoarelor aplicaţii ale
parcurgerilor: determinarea componentelor conexe, determinarea componentelor
tare conexe şi sortarea topologică.

Competenţe
La sfârşitul acestui modul studenţii vor fi capabili să:
 Parcurgă grafuri;
 Determine componentele conexe ale unui graf orientat sau neorientat;
 Determine componentele tare conexe ale unui graf orientat;
 Sorteze topologic un digraf fără circuite.

20
Unitatea de învăţare M2.U1. Parcurgerea generică

Cuprins
M2.U1.1. Introducere .................................................................................................... 21
M2.U1.2. Obiectivele unităţii de învăţare ..................................................................... 22
M2.U1.3. Algoritmul de parcurgere generică ............................................................... 22
M2.U1.4. Algoritmul de parcurgere totală generică ..................................................... 27
M2.U1.5. Rezumat ........................................................................................................ 31
M2.U1.6. Test de evaluare a cunoştinţelor ................................................................... 31

M2.U1.1. Introducere
Problema parcurgerii unui digraf G = (N, A) constă în generarea mulţimii W
a nodurilor y accesibile dintr-un nod sursă dat s. Spunem că nodul y este accesibil
din nodul s în digraful G dacă există drum de la nodul sursă s la nodul y. Evident,
W ⊆ N.
Algoritmii pe care îi vom prezenta în acest modul pentru rezolvarea
problemei parcurgerii unui digraf G sunt metode sistematice de vizitare a nodurilor
y accesibile dintr-un nod sursă dat s. Fiecare iteraţie a execuţiei oricărui algoritm
de parcurgere stabileşte pentru fiecare nod apartenenţa la una din următoarele trei
stări:
• nevizitat,
• vizitat şi neanalizat, adică un nod vizitat ai cărui succesori au fost parţial
vizitaţi,
• vizitat şi analizat, adică un nod vizitat ai cărui succesori au fost în
totalitate vizitaţi.

Dacă nodul x este vizitat şi neanalizat, dacă există arc (x, y) şi dacă nodul y
este nevizitat, atunci se poate vizita nodul y. În acest caz se spune că arcul (x, y)
este arc admisibil şi dacă nodul y este vizitat explorând arcul (x, y) se spune că
nodul x este predecesorul-parcurgere al nodului y.
În acest modul se vor prezenta următorii algoritmi pentru parcurgerea unui
digraf: algoritmul generic de parcurgere, algoritmul de parcurgere în lăţime şi
algoritmul de parcurgere în adâncime. Aceşti algoritmi utilizează următoarele
notaţii comune:

21
U mulţimea nodurilor nevizitate;
V mulţimea nodurilor vizitate şi neanalizate;
W mulţimea nodurilor vizitate şi analizate;
p tabloul predecesor, care este unidimensional cu n elemente.

M2.U1.2. Obiectivele unităţii de învăţare


Această unitate de învăţare îşi propune ca obiectiv principal însuşirea de
către studenţi a algoritmilor de parcurgere generică a grafurilor.
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
 parcurgă un digraf, folosind algoritmul de parcurgere generică.

Durata medie de parcurgere a primei unităţi de învăţare este de 3 ore.

M2.U1.3. Algoritmul de parcurgere generică

Se folosesc notaţiile precizate mai sus şi în plus notăm cu o tabloul ordine care este
unidimensional şi are n elemente.
Algoritmul parcurgerii generice (algoritmul PG) este următorul:
algoritm PG;
begin
U = N – {s}; V = {s}; W = Ø;
for y∈ N do p(y) = 0;
k = 1; o(s) = 1;
for y∈ U do o(y) = ∞;
while V ≠ Ø do
begin
se selectează un nod x din V;
if există arc (x, y)∈ A şi y∈ U then
begin
U = U – {y}; V = V ∪ {y}; p(y) = x; k = k+1; o(y) = k;

22
end
else
begin
V = V – {x}; W = W ∪ {x};
end;
end;
end.

Teoremă. Algoritmul PG are complexitatea O(m).

Definiţie. Un digraf G = (N, A) se numeşte arborescenţă cu rădăcina s dacă este fără


cicluri şi ρ⁻(s) = 0, ρ⁻(x) = 1 pentru toate nodurile x din N cu x ≠ s.

Definiţie. Subgraful Gp = (Np, Ap) cu Np = {y∈ N | p(y)≠0} ∪ {s} şi Ap = {(p(y), y) | y∈


Np -{s}} se numeşte subgraf predecesor al digrafului G = (N, A). Dacă Np = W şi Gp este o
arborescenţă atunci Gp se numeşte arborescenţă parcurgere generică. Arcele din Ap se
numesc arce arborescenţă.

Teoremă. Algoritmul PG determină elementele tabloului p astfel încât subgraful


predecesor Gp = (Np, Ap) este o arborescenţă parcurgere generică.

Drumul de la nodul sursă s la un nod oarecare y se determină, folosind vectorul


predecesor p, cu următoarea procedură:

procedura drum(s, y, p);


begin
if y = s then se tipăreşte s;
else if p(y) = 0 then se tipăreşte "nu există drum de la " + s + " la " + y;
else
begin
drum(s, p(y), p);
se tipăreşte y;
end;

23
end;

Exemplu. Aplicăm algoritmul generic de parcurgere pe digraful din figura


2.1.

Fig. 2.1

După iniţializări avem: s=1, U = {2, 3, 4, 5}, V = {1}, W = Ø, p = (0, 0, 0,


0, 0), k = 1, o = (1, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selecteză x = 1 (nodul 1 fiind singurul nod din V). Avem
(1, 2)∈ A, 2∈ U, deci U = {3, 4, 5}, V = {1, 2}, p = (0, 1, 0, 0, 0), k = 2, o = (1, 2,
∞, ∞, ∞).
Iteraţia 2: Nodul x poate fi oricare dintre nodurile din V. Presupunem că a
fost ales nodul x = 1. Deoarece (1, 3)∈ A, 3∈ U, rezultă U = {4, 5}, V = {1, 2, 3},
p = (0, 1, 1, 0, 0), k = 3, o = (1, 2, 3, ∞, ∞).
Iteraţia 3: Nodul x poate fi oricare dintre nodurile din V. Dacă se selectează
nodul x = 3, cum (3, 5)∈ A, 5∈ U, rezultă U = {4}, V = {1, 2, 3, 5}, p = (0, 1, 1,
0, 3), k = 4, o = (1, 2, 3, ∞, 4).
Iteraţia 4: Presupunem că a fost selectat nodul x = 1 din V. Deoarece nu
există arc de la nodul 1 la un nod nevizitat, înseamnă că nodul 1 este vizitat şi
analizat, deci V = {2, 3, 5}, W = {1}.
Iteraţia 5: Dacă se selectează nodul x = 3 din V, atunci V = {2, 5}, W = {1,
3}.
Iteraţia 6: Dacă se selectează nodul x = 2, cum (2, 4)∈ A, 4∈ U, rezultă U =
Ø, V = {2, 4,5}, p = (0, 1, 1, 2, 3), k = 5, o = (1, 2, 3, 5, 4).
Iteraţia 7: Considerăm că se selectează nodul x = 2 din V. Deoarece nu mai
sunt noduri nevizitate rezultă că V = {4, 5}, W = {1, 2, 3}.
Iteraţia 8: Presupunem că se selectează nodul x = 5 din V, atunci V = {4},

24
W = {1, 2, 3, 5}.
Iteraţia 9: Se selectează nodul x = 4 din V. Obţinem V = Ø, W = {1, 2, 3, 4,
5} şi algoritmul se termină.

La terminarea parcurgerii, p = (0, 1, 1, 2, 3), o = (1, 2, 3, 5, 4) şi W = N,


ceea ce însemnă că toate nodurile digrafului sunt accesibile din nodul sursă s = 1.
Cu ajutorul vectorului predecesor p, determinăm arborescenţa parcurgere
generică din figura 2.2.

Fig. 2.2

Datorită faptului că algoritmul generic de parcurgere nu specifică nicio regulă de


selectare a nodului vizitat şi neanalizat x din care se continuă procesul de vizitare a nodurilor
nevizitate, l-am ales “aleator” pe x. De aceea, acest rezultat al parcurgerii nu este singurul
rezultat corect. Alegând alte noduri x din V decât cele alese în exemplul anterior se vor obţine
alţi vectori o şi/sau p. În cazul în care se obţine un alt vector predecesor, evident că se va
determina şi o altă arborescenţă parcurgere generică.

Exemplu. Aplicăm algoritmul generic de parcurgere pe digraful din figura


2.3.

Fig. 2.3

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6}, V = {1}, W = Ø, p = (0, 0,


0, 0, 0, 0), k = 1, o = (1, ∞, ∞, ∞, ∞, ∞).

25
Iteraţia 1: Se selectează x = 1. Avem (1, 2)∈ A, 2∈ U, deci U = {3, 4, 5, 6},
V = {1, 2}, p = (0, 1, 0, 0, 0, 0), k = 2, o = (1, 2, ∞, ∞, ∞, ∞).
Iteraţia 2: Dacă dintre nodurile vizitate şi neanalizate a fost selectat nodul
x = 2, atunci, deoarece (2, 3)∈ A, 3 ∈ U, obţinem U = {4, 5, 6}, V = {1, 2, 3}, p =
(0, 1, 2, 0, 0, 0), k = 3, o = (1, 2, 3, ∞, ∞, ∞).
Iteraţia 3: Presupunem că se selectează nodul x = 1 din V, atunci V = {2, 3}
şi W = {1}.
Iteraţia 4: Considerăm că se selectează nodul x = 3 din V. Deoarece
(3, 5)∈ A, 5∈ U, obţinem U = {4, 6}, V = {2, 3, 5}, p = (0, 1, 2, 0, 3, 0), k = 4, o
= (1, 2, 3, ∞, 4, ∞).
Iteraţia 5: Presupunem că se selectează nodul x = 2 din V, atunci V = {3, 5}
şi W = {1, 2}.
Iteraţia 6: Considerăm că se selectează nodul x = 5 din V. Rezultă V = {3}
şi W = {1, 2, 5}.
Iteraţia 7: Se selectează x = 3, rezultă V = Ø şi W = {1, 2, 3, 5} şi algoritmul
se termină deoarece nu mai există noduri vizitate şi neanalizate.

La terminarea execuţiei algoritmului, avem p = (0, 1, 2, 0, 3, 0), o = (1, 2,


3, ∞, 4, ∞) şi W = {1, 2, 3, 5}, ceea ce însemnă că nodurile 4 şi 6 nu sunt
accesibile din nodul sursă s = 1. Cu ajutorul vectorului predecesor p, determinăm
arborescenţa parcurgere generică din figura 2.4.

Fig. 2.4

26
M2.U1.4. Algoritmul de parcurgere totală generică

În general, mulţimea W a nodurilor accesibile din nodul sursă dat este o submulţime a
mulţimii nodurilor N. Pentru parcurgerea întregului digraf G = (N, A) se utilizează algoritmul
parcurgerii totale generice (algoritmul PTG) prezentat în continuare.

algoritm PTG;
begin
U = N – {s}; V = {s}; W = Ø;
for y∈ N do p(y) = 0;
k = 1; o(s) = 1;
while W ≠ N do
begin
while V ≠ Ø do
begin
se selectează un nod x din V;
if există arc (x, y)∈ A şi y∈ U then
begin
U = U – {y}; V = V ∪ {y}; p(y) = x; k = k+1; o(y) = k;
end
else
begin
V = V – {x}; W = W ∪ {x};
end;
end;
if U ≠ Ø then
begin
se selectează un nou nod sursă s din U;
U = U – {s}; V = {s}; k = k+1; o(s) = k;
end;
end;
end.

Teoremă Algoritmul PTG are complexitatea O(m).

27
Fie mulţimea S={s | s ∈ N, s este nod sursă selectat la începutul sau pe parcursul
execuţiei algoritmului}.
În parcurgerea totală generică, dacă subgraful predecesor Gp = (Np, Ap) cu Np ={y∈ N |
p(y) ≠ 0} ∪ S, Ap ={(p(y), y) | y∈ Np -S} este o pădure şi Np = W, atunci Gp se numeşte pădure
parcurgere.
Algoritmul PTG determină elementele tabloului p astfel încât subgraful predecesor Gp =
(Np, Ap) este o pădure parcurgere (adică este format din una sau mai multe arborescenţe
parcurgere).

Exemplu. Aplicăm algoritmul generic de parcurgere totală pe digraful din


figura 2.5.

Fig. 2.5

După iniţializări avem: s=1, U = {2, 3, 4}, V = {1}, W = Ø, p = (0, 0, 0,


0), k = 1, o = (1, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 2)∈ A, 2∈ U, obţinem U = {3, 4}, V = {1, 2}, p = (0, 1, 0, 0), k = 2, o = (1, 2,
∞, ∞).
Iteraţia 2: Presupunem că a fost ales nodul x = 1 din V. Deoarece (1, 3)∈ A,
3∈ U, rezultă U = {4}, V = {1, 2, 3}, p = (0, 1, 1, 0), k = 3, o = (1, 2, 3, ∞).
Iteraţia 3: Considerăm că se selectează nodul x = 3. Vom obţine V = {1, 2}
şi W = {3}.
Iteraţia 4: Presupunem că se selectează nodul x = 1 din V. Deoarece (1, 4)∈
A, 4∈ U, rezultă U = Ø, V = {1, 2, 4}, p = (0, 1, 1, 1), k = 4, o = (1, 2, 3, 4).
Iteraţia 5: Dacă se selectează nodul x = 4 din V, atunci V = {1, 2} şi W = {3,

28
4}.
Iteraţia 6: Considerăm că se selectează nodul x = 2. Vom obţine V = {1} şi
W = {2, 3, 4}.
Iteraţia 7: Se selectează nodul x = 1 din V şi obţinem V = Ø, W = {1, 2, 3,
4} şi algoritmul se termină.

La terminarea parcurgerii, avem p = (0, 1, 1, 1) şi o = (1, 2, 3, 4). Cu


ajutorul vectorului predecesor p, determinăm pădurea parcurgere care este
formată dintr-o singură arborescenţă, reprezentată în figura 2.6.

Fig. 2.6

Exemplu. Aplicăm algoritmul generic de parcurgere totală pe digraful din


figura 2.7.

Fig. 2.7

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6}, V = {1}, W = Ø, p = (0, 0,


0, 0, 0, 0), k = 1, o = (1, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează x = 1. Deoarece (1, 2)∈ A, 2∈ U, obţinem U = {3,
4, 5, 6}, V = {1, 2}, p = (0, 1, 0, 0, 0, 0), k = 2, o = (1, 2, ∞, ∞, ∞, ∞).
Iteraţia 2: Dacă dintre nodurile vizitate şi neanalizate a fost selectat nodul

29
x = 2, atunci, deoarece (2, 3)∈ A, 3 ∈ U, obţinem U = {4, 5, 6}, V = {1, 2, 3}, p =
(0, 1, 2, 0, 0, 0), k = 3, o = (1, 2, 3, ∞, ∞, ∞).
Iteraţia 3: Presupunem că se selectează nodul x = 1 din V, atunci V = {2, 3}
şi W = {1}.
Iteraţia 4: Considerăm că se selectează nodul x = 3 din V. Deoarece
(3, 5)∈ A, 5∈ U, obţinem U = {4, 6}, V = {2, 3, 5}, p = (0, 1, 2, 0, 3, 0), k = 4, o
= (1, 2, 3, ∞, 4, ∞).
Iteraţia 5: Presupunem că se selectează nodul x = 2 din V, atunci V = {3, 5}
şi W = {1, 2}.
Iteraţia 6: Considerăm că se selectează nodul x = 5 din V. Rezultă V = {3}
şi W = {1, 2, 5}.
Iteraţia 7: Se selectează x = 3, rezultă V = Ø şi W = {1, 2, 3, 5} şi, deoarece
nu mai există noduri vizitate şi neanalizate, algoritmul va selecta un nou nod
sursă dintre nodurile încă nevizitate. Fie acesta nodul 4. Deci, s = 4, U = {6}, V =
{4}, k = 5 şi o = (1, 2, 3, 5, 4, ∞).
Iteraţia 8: Se selectează x = 4. Deoarece (4, 6)∈ A, 6∈ U, obţinem U = Ø, V
= {4, 6}, p = (0, 1, 2, 0, 3, 4), k = 6, o = (1, 2, 3, 5, 4, 6).
Iteraţia 9: Considerăm că se selectează nodul x = 4 din V. Rezultă V = {6}
şi W = {1, 2, 3, 4, 5}.
Iteraţia 10: Se selectează x = 6, rezultă V = Ø şi W = {1, 2, 3, 4, 5, 6} şi
algoritmul se termină.

La finalul algoritmului, avem p = (0, 1, 2, 0, 3, 4) şi o = (1, 2, 3, 5, 4, 6).


Deoarece au existat două noduri sursă (nodul 1 şi nodul 4), se va obţine, cu
ajutorul vectorului predecesor p, o pădure parcurgere formată din două
arborescenţe parcurgere (una cu rădăcina 1 şi cealaltă cu rădăcina 4), care sunt
reprezentate în figura 2.8.

30
Fig. 2.8

M2.U1.5. Rezumat
Algoritmii de parcurgere a unui graf sunt metode sistematice de vizitare a
nodurilor grafului, pornind dintr-un nod sursă. În cazul algoritmului generic de
parcurgere (totală) nodul din care se continuă parcurgerea este selectat, fără nicio
regulă, dintre nodurile vizitate şi neanalizate.

M2.U1.6. Test de evaluare a cunoştinţelor

1. Aplicaţi algoritmul de parcurgere generică pe următorul digraf:

2. Aplicaţi algoritmul de parcurgere generică totală pe următorul digraf:

31
Unitatea de învăţare M2.U2. Parcurgerea în lăţime

Cuprins
M2.U2.1. Introducere .................................................................................................... 32
M2.U2.2. Obiectivele unităţii de învăţare ..................................................................... 32
M2.U2.3. Parcurgerea în lăţime .................................................................................... 33
M2.U2.4. Parcurgerea totală în lăţime .......................................................................... 37
M2.U2.5. Rezumat ........................................................................................................ 41
M2.U2.6. Test de evaluare a cunoştinţelor ................................................................... 41

M2.U2.1. Introducere

Algoritmul generic de parcurgere (totală) nu specifică nicio regulă de


selectare a nodului vizitat şi neanalizat x din care se continuă vizitarea nodurilor.
Impunând diferite reguli de selectare a nodului x, se obţin diferiţi algoritmi de
parcurgere a unui digraf G = (N, A). Cei mai utilizaţi algoritmi de parcurgere sunt:
• parcurgerea în lăţime, în engleză breadth first (BF),
• parcurgerea în adâncime, în engleză depth first (DF).

M2.U2.2. Obiectivele unităţii de învăţare


Această unitate de învăţare îşi propune ca obiectiv principal însuşirea de
către studenţi a algoritmilor de parcurgere în lăţime a grafurilor.
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
 parcurgă un digraf, folosind algoritmul de parcurgere în lăţime.

Durata medie de parcurgere a acestei unităţi de învăţare este de 3 ore.

32
M2.U2.3. Parcurgerea în lăţime

Fie digraful G =(N, A) cu nodul sursă s şi ∆x mulţimea drumurilor de la nodul sursă s la


nodul x∈ N. Numărul de arce care compun un drum Dx∈ ∆x defineşte lungimea acestui drum
pe care o notăm cu l(Dx). Distanţa de la nodul s la nodul x se defineşte în modul următor:

min{l ( Dx ) | Dx ∈ ∆ x }, daca ∆ x ≠ ∅

d ( x) = 
 ∞, daca ∆ x = ∅

Un drum Dx∈ ∆x cu l(Dx) = d(x) se numeşte cel mai scurt drum de la nodul sursă s la
nodul x.
În algoritmul parcurgerii BF (algoritmul PBF) se folosesc aceleaşi notaţii ca în
algoritmul PG cu deosebirea că în locul tabloului ordine o se utilizează tabloul lungime l care
este unidimensional şi are n elemente. Mulţimea nodurilor vizitate şi neanalizate V este
organizată, ca structură de date, ca o coadă. Algoritmul PBF este următorul:

algoritm PBF;
begin
U = N – {s}; V = {s}; W = Ø;
for y∈ N do p(y) = 0;
l(s) = 0;
for y∈ U do l(y) = ∞;
while V ≠ Ø do
begin
se selectează cel mai vechi nod x introdus în V;
for (x, y)∈ A do
if y∈ U then
begin
U = U – {y}; V = V ∪ {y}; p(y) = x; l(y) = l(x) + 1;
end
V = V – {x}; W = W ∪ {x};
end;
end.

33
Teoremă. Algoritmul PBF are complexitatea O(m).

În parcurgerea BF, dacă Np =W şi subgraful predecesor Gp = (Np, Ap) este o


arborescenţă atunci Gp se numeşte arborescenţă parcurgere BF.

Teoremă. Algoritmul PBF determină:


a) elementele tabloului l astfel încât l(y) = d(y) pentru y∈ N.
b) elementele tabloului p astfel încât subgraful predecesor Gp = (Np, Ap) este o
arborescenţă parcurgere BF

Exemplu
Aplicăm algoritmul de parcurgere în lăţime pe digraful din figura 2.9.

Fig. 2.9

Deoarece mulţimea V trebuie organizată ca o coadă, vom scrie la sfârşitul


ei nodurile nou adăugate şi vom extrage întotdeauna primul nod din V.

După iniţializări avem: s=1, U = {2, 3, 4, 5}, V = {1}, W = Ø, p = (0, 0, 0,


0, 0), l = (0, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1. Deoarece (1, 2)∈ A şi 2∈ U, obţinem
U = {3, 4, 5}, V = {1, 2}, p = (0, 1, 0, 0, 0), l = (0, 1, ∞, ∞, ∞). Avem (1, 3)∈ A şi
3∈ U, deci U = {4, 5}, V = {1, 2, 3}, p = (0, 1, 1, 0, 0), l = (0, 1, 1, ∞, ∞). Cum
(1, 5)∈ A şi 5∈ U, obţinem U = {4}, V = {1, 2, 3, 5}, p = (0, 1, 1, 0, 1), l = (0, 1,
1, ∞, 1). Se actualizează mulţimile V şi W: V = {2, 3, 5} şi W = {1}.
Iteraţia 2: Se selectează cel mai vechi nod din V, acesta este x = 2.
Deoarece nu există succesori nevizitaţi ai nodului 2, se efectuează V = {3, 5} şi W
= {1, 2}.
Iteraţia 3: Cel mai vechi nod din V este x = 3. Deoarece (3, 4)∈ A şi 4∈ U,
obţinem U = Ø, V = {3, 5, 4}, p = (0, 1, 1, 3, 1), l = (0, 1, 1, 2, 1). Se fac

34
actualizările: V = {5, 4} şi W = {1, 2, 3}.
Iteraţia 4: Se selectează cel mai vechi nod din V, acesta este x = 5.
Deoarece nu mai există noduri nevizitate, se efectuează V = {4} şi W = {1, 2, 3,
5}.
Iteraţia 5: Se selectează nodul x = 4. Obţinem V = Ø, W = {1, 2, 3, 4, 5} şi
algoritmul se termină.

După parcurgerea în lăţime am obţinut, p = (0, 1, 1, 3, 1), l = (0, 1, 1, 2, 1)


şi W = N, ceea ce înseamnă că toate nodurile digrafului sunt accesibile din nodul
sursă s = 1. Cu ajutorul vectorului predecesor p, determinăm arborescenţa
parcurgere BF, care este reprezentată în figura 2.10.

Fig. 2.10

Evident, drumul unic de la s = 1 la orice nod y∈ Np din arborescenţa


parcurgere BF este un cel mai scurt drum de la s la y în digraful G = (N, A).

Exemplu. Aplicăm algoritmul de parcurgere în lăţime pe digraful din


figura 2.11.

Fig. 2.11

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6, 7}, V = {1}, W = Ø, p = (0,

35
0, 0, 0, 0, 0, 0), l = (0, ∞, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1. Deoarece (1, 2)∈ A şi 2∈ U, obţinem
U = {3, 4, 5, 6, 7}, V = {1, 2}, p = (0, 1, 0, 0, 0, 0, 0), l = (0, 1, ∞, ∞, ∞, ∞, ∞).
Avem (1, 5)∈ A şi 5 ∈ U, deci U = {3, 4, 6, 7}, V = {1, 2, 5}, p = (0, 1, 0, 0, 1, 0,
0), l = (0, 1, ∞, ∞, 1, ∞, ∞). Cum (1, 6)∈ A şi 6 ∈ U, obţinem U = {3, 4, 7}, V =
{1, 2, 5, 6}, p = (0, 1, 0, 0, 1, 1, 0), l = (0, 1, ∞, ∞, 1, 1, ∞). Se actualizează
mulţimile V şi W: V = {2, 5, 6} şi W = {1}.
Iteraţia 2: Se selectează cel mai vechi nod din V, acesta este x = 2.
Deoarece nu există succesori nevizitaţi ai nodului 2, se efectuează V = {5, 6} şi W
= {1, 2}.
Iteraţia 3: Cel mai vechi nod din V este x = 5. Deoarece (5, 3)∈ A şi 3∈ U,
obţinem U = {4, 7}, V = {5, 6, 3}, p = (0, 1, 5, 0, 1, 1, 0), l = (0, 1, 2, ∞, 1, 1, ∞).
Se fac actualizările: V = {6, 3} şi W = {1, 2, 5}.
Iteraţia 4: Se selectează cel mai vechi nod din V, acesta este x = 6.
Deoarece nodul 6 nu are succesori nevizitaţi, se efectuează V = {3} şi W = {1, 2,
5, 6}.
Iteraţia 5: Se selectează nodul x = 3. Obţinem V = Ø, W = {1, 2, 3, 5, 6} şi
algoritmul se termină.

La sfârşitul algoritmlui de parcurgere în lăţime am obţinut, p = (0, 1, 5, 0,


1, 1, 0), l = (0, 1, 2, ∞, 1, 1, ∞) şi W = {1, 2, 3, 5, 6}, ceea ce înseamnă că
nodurile 4 şi 7 nu sunt accesibile din nodul sursă s = 1. Cu ajutorul vectorului
predecesor p, determinăm arborescenţa parcurgere BF, care este reprezentată în
figura 2.12.

Fig. 2.12

36
M2.U2.4. Parcurgerea totală în lăţime

Observaţie. În general, mulţimea W a nodurilor accesibile din nodul sursă dat este o
submulţime a mulţimii nodurilor N. Pentru parcurgerea în lăţime a întregului digraf G = (N,
A) se utilizează algoritmul parcurgerii totale în lăţime (algoritmul PTBF), care este următorul:

algoritm PTBF;
begin
U = N – {s}; V = {s}; W = Ø;
for y∈ N do p(y) = 0;
l(s) = 0;
while W ≠ N do
begin
while V ≠ Ø do
begin
se selectează cel mai vechi nod x introdus în V;
for (x, y)∈ A do
if y∈ U then
begin
U = U – {y}; V = V ∪ {y}; p(y) = x; l(y) = l(x) + 1;
end
V = V – {x}; W = W ∪ {x};
end;
if U ≠ Ø then
begin
se selectează un nou nod sursă s din U;
U = U – {s}; V = {s}; l(s) = 0;
end;
end;
end.

37
Fie mulţimea S={s | s ∈ N, s este nod sursă selectat la începutul sau pe parcursul
execuţiei algoritmului}.
În parcurgerea totală BF, dacă subgraful predecesor Gp = (Np, Ap) cu Np = {y∈ N |
p(y) ≠ 0} ∪ S, Ap ={(p(y), y) | y∈ Np -S} este o pădure şi Np = W, atunci Gp se numeşte pădure
parcurgere BF.
Algoritmul PTBF determină elementele tabloului p astfel încât subgraful predecesor Gp
= (Np, Ap) este o pădure parcurgere BF.

Exemplu Aplicăm algoritmul de parcurgere totală în lăţime pe digraful din


figura 2.13.

Fig. 2.13

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6}, V = {1}, W = Ø, p = (0, 0,


0, 0, 0, 0), l = (0, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1. Deoarece (1, 2)∈ A şi 2∈ U, obţinem
U = {3, 4, 5, 6}, V = {1, 2}, p = (0, 1, 0, 0, 0, 0), l = (0, 1, ∞, ∞, ∞, ∞). Avem (1,
3)∈ A şi 3 ∈ U, deci U = {4, 5, 6}, V = {1, 2, 3}, p = (0, 1, 1, 0, 0, 0), l = (0, 1, 1,
∞, ∞, ∞). Se actualizează mulţimile V şi W: V = {2, 3} şi W = {1}.
Iteraţia 2: Se selectează cel mai vechi nod din V, acesta este x = 2.
Deoarece (2, 4)∈ A şi 4∈ U, obţinem U = {5, 6}, V = {2, 3, 4}, p = (0, 1, 1, 2, 0,
0), l = (0, 1, 1, 2, ∞, ∞). Avem (2, 5)∈ A şi 5∈ U, deci U = {6}, V = {2, 3, 4, 5},
p = (0, 1, 1, 2, 2, 0), l = (0, 1, 1, 2, 2, ∞). Se efectuează V = {3, 4, 5} şi W = {1,
2}.
Iteraţia 3: Cel mai vechi nod din V este x = 3. Dar nodul 3 nu are succesori
nevizitaţi, deci V = {4, 5} şi W = {1, 2, 3}.
Iteraţia 4: Se selectează cel mai vechi nod din V, acesta este x = 4. Avem
(4, 6)∈ A şi 6∈ U, deci U = Ø, V = {4, 5, 6}, p = (0, 1, 1, 2, 2, 4), l = (0, 1, 1, 2, 2,
3). Se efectuează V = {5, 6} şi W = {1, 2, 3, 4}.
Iteraţia 5: Se selectează nodul x = 5, care este cel mai vechi nod din V.

38
Deoarece nu mai există noduri nevizitate, se efectuează V = {6} şi W = {1, 2, 3,
4, 5}.
Iteraţia 6: Se selectează nodul x = 6. Se efectuează V = Ø, W = {1, 2, 3, 4,
5, 6} şi algoritmul se termină.

Deoarece toate nodurile au fost vizitate pornind din nodul sursă s = 1 (nu a
fost necesar să selectăm noi noduri sursă) rezultatul parcurgerii totale în lăţime ar
fi putut fi obţinut şi cu algoritmul de parcurgere în lăţime. Deci, s-a obţinut o
singură arborescenţa parcurgere BF, care este reprezentată în figura 2.14.

Fig. 2.14

Exemplu Aplicăm algoritmul de parcurgere totală în lăţime pe digraful din


figura 2.15.

Fig. 2.15

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6, 7}, V = {1}, W = Ø, p = (0,


0, 0, 0, 0, 0, 0), l = (0, ∞, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1. Deoarece (1, 2)∈ A şi 2∈ U, obţinem
U = {3, 4, 5, 6, 7}, V = {1, 2}, p = (0, 1, 0, 0, 0, 0, 0), l = (0, 1, ∞, ∞, ∞, ∞, ∞).
Avem (1, 5)∈ A şi 5 ∈ U, deci U = {3, 4, 6, 7}, V = {1, 2, 5}, p = (0, 1, 0, 0, 1, 0,
0), l = (0, 1, ∞, ∞, 1, ∞, ∞). Se actualizează mulţimile V şi W: V = {2, 5} şi W =
{1}.

39
Iteraţia 2: Se selectează cel mai vechi nod din V, acesta este x = 2.
Deoarece nodul 2 nu are succesori, se efectuează V = {5} şi W = {1, 2}.
Iteraţia 3: Cel mai vechi nod din V este x = 5. Deoarece nici nodul 5 nu are
succesori nevizitaţi, obţinem V = Ø şi W = {1, 2, 5}. Se determină un nou nod
sursă dintre nodurile nevizitate (din U). Fie acesta s = 3. Se fac actualizările U =
{4, 6, 7}, V = {3}, l = (0, 1, 0, ∞, 1, ∞, ∞).
Iteraţia 4: Se selectează singurul nod din V, acesta este x = 3. Deoarece
nodul 3 nu are succesori nevizitaţi, se efectuează V = Ø şi W = {1, 2, 3, 5}. Se
determină un nou nod sursă dintre nodurile nevizitate. Fie acesta s = 4. Se fac
actualizările U = {6, 7}, V = {4}, l = (0, 1, 0, 0, 1, ∞, ∞).
Iteraţia 5: Se selectează nodul x = 4. Deoarece (4, 6)∈ A şi 6∈ U, obţinem
U = {7}, V = {4, 6}, p = (0, 1, 0, 0, 1, 4, 0), l = (0, 1, 0, 0, 1, 1, ∞). Avem (4, 7)∈
A şi 7∈ U, deci U = Ø, V = {4, 6, 7}, p = (0, 1, 0, 0, 1, 4, 4), l = (0, 1, 0, 0, 1, 1,
1). Se actualizează mulţimile V şi W: V = {6, 7} şi W = {1, 2, 3, 4, 5}.
Iteraţia 6: Cel mai vechi nod din V este x = 6. Deoarece nu mai sunt noduri
nevizitate, obţinem V = {7} şi W = {1, 2, 3, 4, 5, 6}.
Iteraţia 7: Singurul nod din V este x = 7. Se efectuează V = Ø, W = {1, 2, 3,
4, 5, 6, 7} şi algoritmul se termină.

La sfârşitul algoritmlui de parcurgere totală în lăţime am obţinut, p = (0, 1,


0, 0, 1, 4, 4), l = (0, 1, 0, 0, 1, 1, 1). Cu ajutorul vectorului predecesor p,
determinăm pădurea parcurgere BF formată din cele trei arborescenţe care au ca
noduri rădăcină nodurile sursă selectate în algoritm (nodurile 1, 3 şi 4) şi care
sunt reprezentate în figura 2.16.

Fig. 2.16

40
M2.U2.5. Rezumat
Algoritmul de parcurgere (totală) în lăţime a unui graf este o metodă
sistematică de vizitare a nodurilor grafului, pornind dintr-un nod sursă. Întotdeauna
nodul din care se continuă parcurgerea este cel mai vechi dintre nodurile vizitate şi
neanalizate. Deci, putem obţine algoritmul de parcurgere (totală) în lăţime
organizând ca o coadă a mulţimea V a nodurilor vizitate şi neanalizate din algoritmul
generic de parcurgere (totală).

M2.U2.6. Test de evaluare a cunoştinţelor

1. Aplicaţi algoritmul de parcurgere în lăţime pe următorul digraf:

2. Aplicaţi algoritmul de parcurgere totală în lăţime pe următorul digraf:

41
Unitatea de învăţare M2.U3. Parcurgerea în adâncime

Cuprins
M2.U3.1. Introducere .................................................................................................... 42
M2.U3.2. Obiectivele unităţii de învăţare ..................................................................... 42
M2.U3.3. Parcurgerea în adâncime............................................................................... 43
M2.U3.4. Parcurgerea totală în adâncime ..................................................................... 47
M2.U3.5. Rezumat ........................................................................................................ 54
M2.U3.6. Test de evaluare a cunoştinţelor ................................................................... 54

M2.U3.1. Introducere

Una dintre cele mai des utilizate implementări ale algoritmului generic de
parcurgere (totală) este algoritmul de parcurgere (totală) în adâncime. Acesta
constă, după cum numele său sugerează, în a vizita cât mai “adânc” graful. Pentru
aceasta, la fiecare pas, se continua parcurgerea din ultimul nod vizitat, dacă el are
măcar un successor nevizitat, iar, în caz contrar, se revine la nodul din care el a
fost vizitat.

M2.U3.2. Obiectivele unităţii de învăţare


Această unitate de învăţare îşi propune ca obiectiv principal însuşirea de
către studenţi a algoritmilor de parcurgere în adâncime a grafurilor.
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
 parcurgă un digraf, folosind algoritmul de parcurgere în adâncime.

Durata medie de parcurgere a acestei unităţi de învăţare este de 3 ore.

42
M2.U3.3. Parcurgerea în adâncime

În algoritmul de parcurgere în adâncime (algoritmul PDF) se folosesc aceleaşi notaţii ca


în algoritmul PG cu deosebirea că în locul tabloului unidimensional ordine o se utilizează
tablourile timp unidimensionale t1 şi t2 care au fiecare n elemente. În t1(x) se reţine momentul
când x devine nod vizitat şi neanalizat, iar în t2(x) momentul când x devine nod vizitat şi
analizat, x∈ N. Mulţimea nodurilor vizitate şi neanalizate V este organizată, ca structură de
date, ca o stivă.
Algoritmul PDF este următorul:

algoritm PDF;
begin
U = N – {s}; V = {s}; W = Ø;
for y∈ N do p(y) = 0;
t = 1; t1(s) = 1;
for y∈ U do
begin
t1(y) = ∞; t2(y) = ∞;
end;
while V ≠ Ø do
begin
se selectează cel mai nou nod x introdus în V;
if există arc (x,y)∈ A şi y∈ U then
begin
U = U – {y}; V = V ∪ {y}; p(y) = x; t = t +1;t1(y)= t;
end
else
begin
V = V – {x}; W = W ∪ {x}; t = t +1; t2(x)= t;
end;
end;
end.

Teoremă Algoritmul PDF are complexitatea O(m).

43
În parcurgerea DF, dacă Np =W şi subgraful predecesor Gp = (Np, Ap) este o arborescenţă
atunci Gp se numeşte arborescenţă parcurgere DF.

Exemplu Aplicăm algoritmul de parcurgere în adâncime pe digraful din


figura 2.17.
Deoarece mulţimea V trebuie organizată ca o stivă, vom scrie la sfârşitul ei
nodurile nou adăugate şi vom extrage întotdeauna ultimul nod din V.
După iniţializări avem: s=1, U = {2, 3, 4}, V = {1}, W = Ø, p = (0, 0, 0,
0), t = 1, t1 = (1, ∞, ∞, ∞), t2 = (∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 2)∈ A, 2∈ U, obţinem U = {3, 4}, V = {1, 2}, p = (0, 1, 0, 0), t = 2, t1 = (1, 2,
∞, ∞).

Fig. 2.17

Iteraţia 2: Cel mai nou nod din V este x = 2. Avem (2, 3)∈ A, 3∈ U,
obţinem U = {4}, V = {1, 2, 3}, p = (0, 1, 2, 0), t = 3, t1 = (1, 2, 3, ∞).
Iteraţia 3: Se selectează cel mai nou nod din V, acesta este x = 3. Deoarece
nodul 3 nu are succesori nevizitaţi, se efectuează V = {1, 2}, W = {3}, t = 4, t2 =
(∞, ∞, 4, ∞).
Iteraţia 4: Cel mai nou nod din V este x = 2. Avem (2, 4)∈ A, 4∈ U,
obţinem U = Ø, V = {1, 2, 4}, p = (0, 1, 2, 2), t = 5, t1 = (1, 2, 3, 5).
Iteraţia 5: Se selectează cel mai nou nod din V, acesta este x = 4. Deoarece
nu mai există noduri nevizitate, se efectuează V = {1, 2}, W = {3, 4}, t = 6, t2 =
(∞, ∞, 4, 6).
Iteraţia 6: Cel mai nou nod din V este x = 2. Se fac actualizările: V = {1},
W = {2, 3, 4}, t = 7, t2 = (∞, 7, 4, 6).

44
Iteraţia 7: Se selectează x = 1. Se efectuează V = Ø, W = {1, 2, 3, 4}, t = 8,
t2 = (8, 7, 4, 6) şi algoritmul se termină.

Fig. 2.18

La finalul algoritmului am obţinut W = {1, 2, 3, 4} (deci toate nodurile


digrafului sunt accesibile din nodul 1), vectorii timp t1 = (1, 2, 3, 5) şi t2 = (8, 7,
4, 6) şi vectorul predecesor p = (0, 1, 2, 2), cu ajutorul căruia determinăm
arborescenţa parcurgere DF ilustrată în figura 2.18.

Exemplu Aplicăm algoritmul de parcurgere în adâncime pe digraful din


figura 2.19.

Fig. 2.19

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6}, V = {1}, W = Ø, p = (0, 0,


0, 0, 0, 0), t = 1, t1 = (1, ∞, ∞, ∞, ∞, ∞), t2 = (∞, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 2)∈ A, 2∈ U, obţinem U = {3, 4, 5, 6}, V = {1, 2}, p = (0, 1, 0, 0, 0, 0), t = 2,
t1 = (1, 2, ∞, ∞, ∞, ∞).
Iteraţia 2: Cel mai nou nod din V este x = 2. Avem (2, 3)∈ A, 3∈ U,
obţinem U = {4, 5, 6}, V = {1, 2, 3}, p = (0, 1, 2, 0, 0, 0), t = 3, t1 = (1, 2, 3, ∞, ∞,

45
∞).
Iteraţia 3: Se selectează cel mai nou nod din V. Acesta este nodul x = 3.
Deoarece (3, 4)∈ A, 4∈ U, obţinem U = {5, 6}, V = {1, 2, 3, 4}, p = (0, 1, 2, 3, 0,
0), t = 4, t1 = (1, 2, 3, 4, ∞, ∞).
Iteraţia 4: Cel mai nou nod din V este x = 4. Avem (4, 5)∈ A, 5∈ U,
obţinem U = {6}, V = {1, 2, 3, 4, 5}, p = (0, 1, 2, 3, 4, 0), t = 5, t1 = (1, 2, 3, 4, 5,
∞).
Iteraţia 5: Se selectează cel mai nou nod din V. Acesta este nodul x = 5.
Deoarece nodul 5 nu are succesori, se efectuează V = {1, 2, 3, 4}, W = {5}, t = 6,
t2 = (∞, ∞, ∞, ∞, 6, ∞).
Iteraţia 6: Se selectează cel mai nou nod din V. Acesta este nodul x = 4.
Deoarece nodul 4 nu are succesori nevizitaţi, se efectuează V = {1, 2, 3}, W = {4,
5}, t = 7, t2 = (∞, ∞, ∞, 7, 6, ∞).
Iteraţia 7: Cel mai nou nod din V este x = 3. Obţinem V = {1, 2}, W = {3, 4,
5}, t = 8, t2 = (∞, ∞, 8, 7, 6, ∞).
Iteraţia 8: Se selectează cel mai nou nod din V. Acesta este nodul x = 2. Se
efectuează V = {1}, W = {2, 3, 4, 5}, t = 9, t2 = (∞, 9, 8, 7, 6, ∞).
Iteraţia 9: Singurul nod din V este x = 1. Obţinem V = Ø, W = {1, 2, 3, 4,
5}, t = 10, t2 = (10, 9, 8, 7, 6, ∞) şi algoritmul se termină.

La sfârşitul algoritmului am obţinut W = {1, 2, 3, 4, 5}, ceea ce înseamnă


că doar nodul 6 nu este accesibil din nodul sursă 1, vectorii timp t1 = (1, 2, 3, 4, 5,
∞) şi t2 = (10, 9, 8, 7, 6, ∞). Cu ajutorul vectorului predecesor p = (0, 1, 2, 3, 4, 0)
determinăm arborescenţa parcurgere DF ilustrată în figura 2.20.

46
Fig. 2.20

M2.U3.4. Parcurgerea totală în adâncime

Aşa cum se observă şi din exemplul anterior, în general, mulţimea W a nodurilor


accesibile din nodul sursă dat este o submulţime a mulţimii nodurilor N. Pentru parcurgerea în
adâncime a întregului digraf G = (N, A) se utilizează algoritmul parcurgerii totale în adâncime
(algoritmul PTDF), care este următorul:

algoritm PTDF;
begin
U = N – {s}; V = {s}; W = Ø;
for y∈ N do p(y) = 0;
t = 1; t1(s) = 1;
while W ≠ N do
begin
while V ≠ Ø do
begin
se selectează cel mai nou nod x introdus în V;

47
if există arc (x,y)∈ A şi y∈ U then
begin
U = U – {y}; V = V ∪ {y}; p(y) = x; t = t +1;t1(y)= t;
end
else
begin
V = V – {x}; W = W ∪ {x}; t = t +1; t2(x)= t;
end;
end;
if U ≠ Ø then
begin
se selectează un nou nod sursă s din U;
U = U – {s}; V = {s}; t = t+ 1; t1(s) = t;
end;
end;
end.

Teoremă Algoritmul PTDF are complexitatea O(m).

Fie mulţimea S={s | s ∈ N, s este nod sursă selectat la începutul sau pe parcursul
execuţiei algoritmului}.
În parcurgerea totală DF, dacă subgraful predecesor Gp = (Np, Ap) cu Np = {y∈ N |
p(y) ≠ 0} ∪ S, Ap ={(p(y), y) | y∈ Np -S} este o pădure şi Np = W, atunci Gp se numeşte pădure
parcurgere DF.
Algoritmul PTDF determină elementele tabloului p astfel încât subgraful predecesor Gp
= (Np, Ap) este o pădure parcurgere DF.
Parcurgerea totală DF poate fi utilizată la clasificarea arcelor digrafului G = (N, A) în
raport cu pădurea parcurgere DF. În această clasificare există două clase de arce:
• arce arborescenţă,
• arce nonarborescenţă.

Mulţimea arcelor arborescenţă, notată P, este P = Ap. Aceste arce introduc, în timpul
parcurgerii totale DF a digrafului G = (N, A), noduri în mulţimea nodurilor vizitate şi

48
neanalizate V. Mulţimea arcelor nonarborescenţă, notată P , este P = A – Ap. Clasa arcelor

nonarborescenţă P este alcătuită din trei subclase:


• arce de înaintare,
• arce de revenire,
• arce de traversare.

Mulţimea arcelor de înaintare, notată I, este alcătuită din acele arce (x, y) pentru care
nodul x este un ascendent al nodului y în pădurea parcurgere DF. Mulţimea arcelor de
revenire, notată R, este alcătuită din acele arce (x, y) pentru care nodul x este un descendent al
nodului y în pădurea parcurgere DF. Mulţimea arcelor de traversare, notată T, este alcătuită
din acele arce (x, y) pentru care nodul x nu este nici ascendent, nici descendent al nodului y în
pădurea parcurgere DF. Aceste trei mulţimi de arce nonarborescenţă sunt disjuncte două câte

două şi P = I ∪ R ∪ T .

Teoremă. Într-o parcurgere totală DF a unui digraf G = (N, A), arcul (x, y) este:
(1) un arc arborescenţă sau de înaintare dacă şi numai dacă t1(x) < t1(y) < t2(y) < t2(x);
(2) un arc de revenire dacă şi numai dacă t1(y) < t1(x) < t2(x) < t2(y);
(3) un arc de traversare dacă şi numai dacă t1(y) < t2(y) < t1(x) < t2(x).

Exemplu Aplicăm algoritmul de parcurgere totală în adâncime pe digraful


din figura 2.21.

Fig. 2.21

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6}, V = {1}, W = Ø, p = (0, 0,


0, 0, 0, 0), t = 1, t1 = (1, ∞, ∞, ∞, ∞, ∞), t2 = (∞, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 2)∈ A, 2∈ U, obţinem U = {3, 4, 5, 6}, V = {1, 2}, p = (0, 1, 0, 0, 0, 0), t = 2,
t1 = (1, 2, ∞, ∞, ∞, ∞).
Iteraţia 2: Cel mai nou nod din V este x = 2. Avem (2, 3)∈ A, 3∈ U, rezultă

49
că U = {4, 5, 6}, V = {1, 2, 3}, p = (0, 1, 2, 0, 0, 0), t = 3, t1 = (1, 2, 3, ∞, ∞, ∞).
Iteraţia 3: Se selectează cel mai nou nod din V. Acesta este nodul x = 3.
Deoarece (3, 4)∈ A, 4∈ U, obţinem U = {5, 6}, V = {1, 2, 3, 4}, p = (0, 1, 2, 3, 0,
0), t = 4, t1 = (1, 2, 3, 4, ∞, ∞).
Iteraţia 4: Cel mai nou nod din V este x = 4. Avem (4, 5)∈ A, 5∈ U,
obţinem U = {6}, V = {1, 2, 3, 4, 5}, p = (0, 1, 2, 3, 4, 0), t = 5, t1 = (1, 2, 3, 4, 5,
∞).
Iteraţia 5: Se selectează cel mai nou nod din V. Acesta este nodul x = 5.
Deoarece nodul 5 nu are succesori, se efectuează V = {1, 2, 3, 4}, W = {5}, t = 6,
t2 = (∞, ∞, ∞, ∞, 6, ∞).
Iteraţia 6: Se selectează cel mai nou nod din V. Acesta este nodul x = 4.
Avem (4, 6)∈ A, 6∈ U, rezultă că U = Ø, V = {1, 2, 3, 4, 6}, p = (0, 1, 2, 3, 4, 4),
t = 7, t1 = (1, 2, 3, 4, 5, 7).
Iteraţia 7: Cel mai nou nod din V este x = 6. Deoarece nu mai sunt noduri
nevizitate, obţinem V = {1, 2, 3, 4}, W = {5, 6}, t = 8, t2 = (∞, ∞, ∞, ∞, 6, 8).
Iteraţia 8: Se selectează cel mai nou nod din V. Acesta este nodul x = 4. Se
efectuează V = {1, 2, 3}, W = {4, 5, 6}, t = 9, t2 = (∞, ∞, ∞, 9, 6, 8).
Iteraţia 9: Cel mai nou nod din V este x = 3. Obţinem V = {1, 2}, W = {3, 4,
5, 6}, t = 10, t2 = (∞, ∞, 10, 9, 6, 8).
Iteraţia 10: Se selectează cel mai nou nod din V. Acesta este nodul x = 2. Se
efectuează V = {1}, W = {2, 3, 4, 5, 6}, t = 11, t2 = (∞, 11, 10, 9, 6, 8).
Iteraţia 11: Singurul nod din V este x = 1. Obţinem V = Ø, W = {1, 2, 3, 4,
5, 6}, t = 12, t2 = (12, 11, 10, 9, 6, 8) şi algoritmul se termină.

50
Fig. 2.22

La sfârşitul algoritmului, p = (0, 1, 2, 3, 4, 4), t1 = (1, 2, 3, 4, 5, 7) şi t2 =


(12, 11, 10, 9, 6, 8). Cu ajutorul vectorului predecesor p, determinăm pădurea
parcurgere DF reprezentată în figura 2.22.

Cu ajutorul vectorilor timp t1 şi t2, clasificăm arcele aşa cum se vede în


figura 2.23, unde pe fiecare arc am trecut mulţimea căreia îi aparţine.

Fig. 2.23

Exemplu
Aplicăm algoritmul de parcurgere totală în adâncime pe digraful din figura
2.24.

51
Fig. 2.24

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6, 7}, V = {1}, W = Ø, p = (0,


0, 0, 0, 0, 0, 0), t = 1, t1 = (1, ∞, ∞, ∞, ∞, ∞, ∞), t2 = (∞, ∞, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 2)∈ A, 2∈ U, obţinem U = {3, 4, 5, 6, 7}, V = {1, 2}, p = (0, 1, 0, 0, 0, 0, 0),
t = 2, t1 = (1, 2, ∞, ∞, ∞, ∞, ∞).
Iteraţia 2: Cel mai nou nod din V este x = 2. Avem (2, 5)∈ A, 5∈ U,
obţinem U = {3, 4, 6, 7}, V = {1, 2, 5}, p = (0, 1, 0, 0, 2, 0, 0), t = 3, t1 = (1, 2, ∞,
∞, 3, ∞, ∞).
Iteraţia 3: Se selectează cel mai nou nod din V. Acesta este nodul x = 5.
Deoarece nodul 5 nu are succesori, se efectuează V = {1, 2}, W = {5}, t = 4, t2 =
(∞, ∞, ∞, ∞, 4, ∞, ∞).
Iteraţia 4: Cel mai nou nod din V este x = 2, care nu are succesori nevizitaţi.
Deci, V = {1}, W = {2, 5}, t = 5, t2 = (∞, 5, ∞, ∞, 4, ∞, ∞).
Iteraţia 5: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 3)∈ A, 3∈ U, obţinem U = {4, 6, 7}, V = {1, 3}, p = (0, 1, 1, 0, 2, 0, 0), t = 6,
t1 = (1, 2, 6, ∞, 3, ∞, ∞).
Iteraţia 6: Cel mai nou nod din V este x =3. Deoarece (3, 4)∈ A, 4∈ U,
obţinem U = {6, 7}, V = {1, 3, 4}, p = (0, 1, 1, 3, 2, 0, 0), t = 7, t1 = (1, 2, 6, 7, 3,
∞, ∞).
Iteraţia 7: Cel mai nou nod din V este x = 4. Deoarece nodul 4 nu are
succesori nevizitaţi, obţinem V = {1, 3}, W = {2, 4, 5}, t = 8, t2 = (∞, 5, ∞, 8, 4,
∞, ∞).
Iteraţia 8: Se selectează x = 3. Deci, V = {1}, W = {2, 3, 4, 5}, t = 9, t2 = (∞,
5, 9, 8, 4, ∞, ∞).
Iteraţia 9: Singurul nod din V este x = 1. Obţinem V = Ø, W = {1, 2, 3, 4,
5}, t = 10, t2 = (10, 5, 9, 8, 4, ∞, ∞). Având noduri nevizitate, selectăm o nouă

52
sursă. Fie aceasta s = 6. Se efectuează U = {7}, V = {6}, t = 11, t1 = (1, 2, 6, 7, 3,
11, ∞).
Iteraţia 10: Se selectează nodul x = 6, fiind singurul nod din V. Deoarece
(6, 7)∈ A, 7∈ U, obţinem U = Ø, V = {6, 7}, p = (0, 1, 1, 3, 2, 0, 6), t = 12, t1 =
(1, 2, 6, 7, 3, 11, 12).
Iteraţia 11: Cel mai nou nod din V este x = 7. Deoarece nu mai sunt noduri
nevizitate, obţinem V = {6}, W = {1, 2, 3, 4, 5, 7}, t = 13, t2 = (10, 5, 9, 8, 4, ∞,
13).
Iteraţia 12: Singurul nod din V este x = 6. Obţinem V = Ø, W = {1, 2, 3, 4,
5, 6, 7}, t = 14, t2 = (10, 5, 9, 8, 4, 14, 13) şi algoritmul se termină.

Fig. 2.25

La sfârşitul algoritmului, p = (0, 1, 1, 3, 2, 0, 6), t1 = (1, 2, 6, 7, 3, 11, 12) şi


t2 = (10, 5, 9, 8, 4, 14, 13). Cu ajutorul vectorului predecesor p, determinăm
pădurea parcurgere DF reprezentată în figura 2.25.
Cu ajutorul vectorilor timp t1 şi t2, clasificăm arcele aşa cum se vede în
figura 2.26, unde pe fiecare arc am trecut mulţimea căreia îi aparţine.

Fig. 2.26

53
M2.U3.5. Rezumat
Algoritmul de parcurgere (totală) în adâncime a unui graf este o metodă
sistematică de vizitare a nodurilor grafului, pornind dintr-un nod sursă. Întotdeauna
nodul din care se continuă parcurgerea este cel mai nou dintre nodurile vizitate şi
neanalizate. Deci, putem obţine algoritmul de parcurgere (totală) în adâncime
organizând ca o stivă a mulţimea V a nodurilor vizitate şi neanalizate din algoritmul
generic de parcurgere (totală).

M2.U3.6. Test de evaluare a cunoştinţelor

1. Aplicaţi algoritmul de parcurgere în adâncime pe următorul digraf:

2. Aplicaţi algoritmul de parcurgere totală în adâncime pe următorul digraf:

54
Unitatea de învăţare M2.U4. Aplicaţii ale parcurgerilor

Cuprins
M2.U4.1. Introducere .................................................................................................... 55
M2.U4.2. Obiectivele unităţii de învăţare ..................................................................... 55
M2.U4.3. Determinarea componentelor conexe ........................................................... 56
M2.U4.4. Determinarea componentelor tare conexe .................................................... 60
M2.U4.5. Sortarea topologică ....................................................................................... 64
M2.U4.6. Rezumat ........................................................................................................ 68
M2.U4.7. Test de evaluare a cunoştinţelor ................................................................... 68

M2.U4.1. Introducere

Problema parcurgerii unui graf poate apărea ca problemă de sine stătătoare


sau ca subproblemă a unei alet probleme. De exemplu, pentru a determina
componentele tare conexe ale unui digraf, este necesară parcurgerea lui în
adâncime. De asemenea, algoritmul de parcurgere în adâncime poate fi modificat
uşor pentru a sorta topologic un digraf fără circuite.
Algoritmul de determinare a componentelor conexe ale unui graf poate fi
obţinut, pornind de la oricare dintre algoritmii de parcurgere. Însă, în vederea unei
abordări unitare a aplicaţiilor parcurgerilor, vom folosi ca punct de plecare tot
algoritmul de parcurgere în adâncime.

M2.U4.2. Obiectivele unităţii de învăţare


Această unitate de învăţare îşi propune ca obiectiv principal însuşirea de
către studenţi a noţiunilor de conexitate, tare conexitate şi sortare topologică.
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
 Determine componenetele conexe ale unui graf;
 Determine componenetele tare conexe ale unui graf;.
 Sorteze topologic un digraf fără circuite.

55
Durata medie de parcurgere a primei unităţi de învăţare este de 3 ore.

M2.U4.3. Determinarea componentelor conexe

Un digraf G = (N, A) se numeşte slab conex sau conex dacă pentru oricare două noduri
diferite x, y există un lanţ care are aceste două noduri drept extremităţi.
Noţiunea de conexitate are sens şi pentru grafuri neorientate.
Se numeşte componentă conexă a unui digraf G = (N, A) un subgraf G´ = (N´, A´) al lui
G, care este conex şi care este maximal în raport cu incluziunea faţă de această proprietate
(oricare ar fi x∈ N - N´, subgraful G x′ generat de N ′x = N´ ∪ {x} nu este conex).

O componentă conexă G´ = (N´, A´) a unui digraf G = (N, A) se poate identifica prin
mulţimea N´ care generează subgraful G´.
Deoarece în problema conexităţii sensul arcelor nu contează, algoritmul va fi descris
pentru grafuri neorientate. Dacă G = (N, A) este digraf atunci i se asociază graful neorientat

Gˆ = ( Nˆ , Aˆ ) , unde N̂ = N, Â ={[x, y]| (x, y) ∈ A sau (y, x) ∈ A}. Este evident că G = (N, A)

şi Gˆ = ( Nˆ , A
ˆ ) au aceleaşi componente conexe (privite ca mulţimi de noduri).
Algoritmul de deteminare a componentelor conexe (algoritmul CC) este o adaptare a
algoritmului PTDF aplicat unui graf neorientat G = (N, A). Nu se calculează tablourile timp t1,
t2 şi nici vectorul predecesor p, în mulţimea N´ reţinem componenta conexă curentă, iar la
sfârşitul algoritmului nc va fi numărul de componte conexe ale grafului. Algoritmul CC este
următorul:

algoritm CC;
begin
U = N – {s}; V = {s}; W = Ø; nc = 1; N' = {s};
while W ≠ N do
begin
while V ≠ Ø do
begin
se selectează cel mai nou nod x introdus în V;

56
if există muchie [x, y]∈ A şi y∈ U then
begin
U = U – {y}; V = V ∪ {y}; N´ = N´ ∪ {y};
end
else
begin
V = V – {x}; W = W ∪ {x};
end;
end;
se tipăresc nc şi N´;
if U ≠ Ø then
begin
se selectează un nou nod sursă s din U;
U = U – {s}; V = {s}; nc = nc+ 1; N´ = {s};
end;
end;
end.

Teoremă Algoritmul CC are complexitatea O(m).

Exemplu Aplicăm algoritmul de determinare a componentelor conexe pe


graful neorientat din figura 2.27.

După iniţializări avem: s=1, U = {2, 3, 4}, V = {1}, W = Ø, N´= {1}, nc =


1.
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
[1, 3]∈ A, 3∈ U, obţinem U = {2, 4}, V = {1, 3}, N´= {1, 3}.
Iteraţia 2: Cel mai nou nod din V este x = 3. Avem [3, 2]∈ A, 2∈ U,
obţinem U = {4}, V = {1, 3, 2}, N´= {1, 2, 3}.

57
Fig. 2.27

Iteraţia 3: Se selectează cel mai nou nod din V. Acesta este nodul x = 2.
Deoarece [2, 4]∈ A, 4∈ U, obţinem U = Ø, V = {1, 3, 2, 4}, N´= {1, 2, 3, 4}.
Iteraţia 4: Cel mai nou nod din V este x = 4. Deoarece nu mai sunt noduri
nevizitate, obţinem V = {1, 3, 2}, W = {4}.
Iteraţia 5: Se selectează cel mai nou nod din V. Acesta este nodul x = 2. Se
efectuează V = {1, 3}, W = {2, 4}.
Iteraţia 6: Cel mai nou nod din V este x = 3. Deci, V = {1}, W = {2, 3, 4}.
Iteraţia 7: Se selectează nodul x = 1. Se efectuează V = Ø, W = {1, 2, 3, 4},
se tipăresc nc=1 şi N´= {1, 2, 3, 4} şi algoritmul se termină.

Deoarece la sfârşitul algoritmului nc=1 înseamnă că graful este conex.

58
Exemplu Pentru a determina componentele conexe ale digrafului din figura
2.28, trebuie mai întâi să determinăm graful neorientat corespunzător lui. Acesta
este reprezentat în figura 2.29.

Fig. 2.28

Fig. 2.29

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6, 7}, V = {1}, W = Ø, N´=


{1}, nc = 1.
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
[1, 2]∈ A, 2∈ U, obţinem U = {3, 4, 5, 6, 7}, V = {1, 2}, N´= {1, 2}.
Iteraţia 2: Cel mai nou nod din V este x = 2. Avem [2, 5]∈ A, 5∈ U,
obţinem U = {3, 4, 6, 7}, V = {1, 2, 5}, N´= {1, 2, 5}.
Iteraţia 3: Se selectează cel mai nou nod din V. Acesta este nodul x = 5.
Deoarece nodul 5 nu are vecini nevizitaţi, se efectuează V = {1, 2}, W = {5}.
Iteraţia 4: Cel mai nou nod din V este x = 2. Obţinem V = {1}, W = {2, 5}.
Iteraţia 5: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
[1, 3]∈ A, 3∈ U, obţinem U = {4, 6, 7}, V = {1, 3}, N´= {1, 2, 3, 5}.
Iteraţia 6: Cel mai nou nod din V este x =3. Deoarece nodul 3 nu are vecini
nevizitaţi, se efectuează V = {1}, W = {2, 3, 5}.
Iteraţia 7: Singurul nod din V este x = 1. Se efectuează V = Ø, W = {1, 2, 3,
5}, se tipăresc nc=1 şi N´= {1, 2, 3, 5}. Deoarece există noduri nevizitate,
selectăm o nouă sursă. Fie aceasta s = 4. Se efectuează U = {6, 7}, V = {4}, nc =

59
2, N´= {4}.
Iteraţia 8: Se selectează x = 4. Fiindcă [4, 6]∈ A, 6∈ U, obţinem U = {7},
V = {4, 6}, N´= {4, 6}.
Iteraţia 9: Cel mai nou nod din V este x = 6. Avem [6, 7]∈ A, 7∈ U,
obţinem U = Ø, V = {4, 6, 7}, N´= {4, 6, 7}.
Iteraţia 10: Se selectează cel mai nou nod din V. Acesta este nodul x = 7.
Deoarece nodul nu mai există noduri nevizitate, se efectuează V = {4, 6}, W = {1,
2, 3, 5, 7}.
Iteraţia 11: Cel mai nou nod din V este x = 6. Obţinem V = {4}, W = {1, 2,
3, 5, 6, 7}.
Iteraţia 12: Singurul nod din V este x = 4. Obţinem V = Ø, W = {1, 2, 3, 4,
5, 6, 7}, se tipăresc nc=2 şi N´= {4, 6, 7} şi algoritmul se termină.

Deci, digraful din figura 2.28 nu este conex, are două componente conexe:
{1, 2, 3, 5} şi {4, 6, 7}. Evident, aceste afirmaţii sunt adevărate şi pentru graful
neorientat din figura 2.29.

M2.U4.4. Determinarea componentelor tare conexe

Un digraf G = (N, A) se numeşte tare conex dacă pentru oricare două noduri diferite x, y
există un drum de la x la y şi un drum de la y la x.
Evident, noţiunea de tare conexitate are sens numai pentru digrafuri.

Se numeşte componentă tare conexă a unui digraf G = (N, A) un subgraf G´ = (N´, A´)
al lui G, care este tare conex şi care este maximal în raport cu incluziunea faţă de această
proprietate (oricare ar fi x∈ N - N´, subgraful G x′ generat de N ′x = N´ ∪ {x} nu este tare
conex).
O componentă tare conexă G´ = (N´, A´) a unui digraf G = (N, A) se poate identifica cu
mulţimea N´ care generează subgraful G´.
Algoritmul de determinare a componentelor tare conexe (algoritmul CTC) este
următorul:

60
algoritm CTC;
begin
se aplică digrafului G algoritmul PTDF pentru a determina vectorul t2;
se determină G-1 graful invers al digrafului G;
se aplică digrafului invers G-1 algoritmul PTDF modificat în modul următor:
nodul sursă s este ales astfel încât t2(s) ≥ t2(x) pentru orice nod nevizitat x, unde t2 este
vectorul timp determinat cu algoritmul PTDF aplicat digrafului G.
se determină componentele tare conexe ale lui G după regula: nodurile care
sunt în aceeaşi arborescenţă DF a digrafului G-1 formează o componentă tare conexă a
lui G.
end.

Teoremă Complexitatea algoritmului CTC este O(m).

Se numeşte digraf condensat asociat digrafului G = (N, A) digraful Ĝ =( N̂ , Â ), N̂

={N1,…,Nq}, Â ={(Ni, Nj) | Ni, Nj∈ N̂ şi există (x, y)∈ A cu x∈ Ni, y∈ Nj}, unde N1,…,Nq
sunt componentele tare conexe ale digrafului G= (N, A).

Exemplu Aplicăm algoritmul de determinare a componentelor tare conexe


pe digraful din figura 2.30.

Fig. 2.30

Aplicând algoritmul PTDF obţinem t2 = (12, 11, 10, 9, 6, 8).


Graful invers al digrafului din figura 2.30 este reprezentat în figura 2.31.

61
Fig. 2.31

Parcurgerea totală DF a grafului invers se începe din nodul sursă s =1


pentru că nodul 1 are cel mai mare timp t2. Nodurile accesibile din nodul 1 în
digraful invers sunt: 1, 2, 3, 4 şi 6. Acestea vor forma prima componentă tare
conexă a digrafului din figura 2.30. Singurul nod rămas nevizitat este nodul 5,
care va constitui cea de-a doua componentă tare conexă a digrafului iniţial. Deci,
digraful nu este tare conex, el având două componente tare conexe {1, 2, 3, 4, 6}
şi {5}.
Digraful condensat este reprezentat în figura 2.32.

Fig. 2.32

Exemplu Aplicăm algoritmul de determinare a componentelor tare conexe


pe digraful din figura 2.33.

Fig. 2.33

Aplicând algoritmul PTDF obţinem t2 = (10, 9, 8, 7, 6, 14, 13).


Se determină graful invers al digrafului din figura 2.33, care este

62
reprezentat în figura 2.34.

Fig. 2.34

Parcurgerea totală DF a grafului invers se începe din nodul sursă s =6,


deoarece el a fost ultimul nod vizitat şi analizat în parcurgerea totală DF a
digrafului iniţial. Nodurile accessibile din 6 sunt 6 şi 7, deci ele formează prima
componentă tare conexă a digrafului iniţial.
Se alege ca nodul sursă nodul 1 deoarece are cel mai mare timp t2 dintre
nodurile rămase nevizitate (1, 2, 3, 4, 5). Din nodul 1 nu se mai poate vizita
niciun alt nod, deci el va forma a doua componentă tare conexă a digrafului din
figura 2.33.
Se selectează s = 2 pentru că nodul 2 are cel mai mare timp t2 dintre
nodurile rămase nevizitate (2, 3, 4, 5). Nodurile accesibile din 2, care sunt 2, 3 şi
4 formează a treia componentă tare conexă.
Singurul nod rămas nevizitat este nodul 5, care va constitui a patra
componentă tare conexă a digrafului iniţial. Deci, componentele tare conexe ale
digrafului din figura 2.33 sunt {1}, {2, 3, 4}, {5} şi {6, 7}, iar corespunzător lor
am obţinut digraful condensat din figura 2.35.

Fig. 2.35

63
M2.U4.5. Sortarea topologică

Sortarea topologică a unui digraf G = (N, A) fără circuite constă în ordonarea nodurilor
din N după regula:
dacă (x, y) ∈ A atunci x < y.
Digrafurile fără circuite sunt folosite în multe aplicaţii pentru a indica relaţia de
anterioritate dintre anumite evenimente.
O modalitate de testare a existenţei circuitelor întrun digraf este dată de următoarea
teoremă.

Teoremă Un digraf G = (N, A) este fără circuite dacă şi numai dacă orice parcurgere
totală DF a lui G nu produce arce de revenire.

Algoritmul sortare topologică (algoritmul ST) se obţine din algoritmul PTDF cu


următoarele modificări:

(1) nodurile sursă s sunt alese astfel încât ρ⁻(s) = 0,

(2) mulţimea W a nodurilor vizitate şi neanalizate este organizată ca o stivă,


(3) nu se mai determină vectorul predecesor p.

La terminarea algoritmului ST, stiva W furnizează sortarea topologică a digrafului G =


(N, A) fără circuite. Se observă că sortarea topologică a nodurilor coincide cu aranjarea lor în
ordinea descrescătoare a timpilor t2 determinaţi cu algoritmul PTDF.

64
Exemplu Aplicăm algoritmul de sortare topologică pe digraful fără circuite
din figura 2.36.

Deoarece mulţimea W trebuie organizată ca o stivă, vom scrie la sfârşitul ei


nodurile nou adăugate.

Fig. 2.36

Iniţial nodul sursă va fi s=1 pentru că ρ⁻(1) = 0.


După iniţializări avem: U = {2, 3, 4, 5}, V = {1}, W = Ø, t = 1, t1 = (1, ∞,
∞, ∞, ∞), t2 = (∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 2)∈ A, 2∈ U, obţinem U = {3, 4, 5}, V = {1, 2}, t = 2, t1 = (1, 2, ∞, ∞, ∞).
Iteraţia 2: Cel mai nou nod din V este x = 2. Avem (2, 4)∈ A, 4∈ U,
obţinem U = {3, 5}, V = {1, 2, 4}, t = 3, t1 = (1, 2, ∞, 3, ∞).
Iteraţia 3: Se selectează cel mai nou nod din V. Acesta este nodul x = 4.
Deoarece nodul 4 nu are succesori, se efectuează V = {1, 2}, W = {4}, t = 4, t2 =
(∞, ∞, ∞, 4, ∞).
Iteraţia 4: Cel mai nou nod din V este x = 2. Avem (2, 5)∈ A, 5∈ U,
obţinem U = {3}, V = {1, 2, 5}, t = 5, t1 = (1, 2, ∞, 3, 5).
Iteraţia 5: Se selectează cel mai nou nod din V. Acesta este nodul x = 5.
Deoarece nodul 5 nu are succesori nevizitaţi, se efectuează V = {1, 2}, W = {4,
5}, t = 6, t2 = (∞, ∞, ∞, 4, 6).
Iteraţia 6: Cel mai nou nod din V este x = 2, care nu mai are succesori
nevizitaţi, deci V = {1}, W = {4, 5, 2}, t = 7, t2 = (∞, 7, ∞, 4, 6).
Iteraţia 7: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 3)∈ A, 3∈ U, obţinem U = Ø, V = {1, 3}, t = 8, t1 = (1, 2, 8, 3, 5).
Iteraţia 8: Cel mai nou nod din V este x = 3. Fiindcă nu mai există noduri
nevizitate, se efectuează V = {1}, W = {4, 5, 2, 3}, t = 9, t2 = (∞, 7, 9, 4, 6).

65
Iteraţia 9: Se selectează nodul x = 1. Obţinem V = Ø, W = {4, 5, 2, 3, 1}, t =
10, t2 = (10, 7, 9, 4, 6) şi algoritmul se termină.

Extrăgând nodurile din stiva W, le obţinem sortate topologic: 1, 3, 2, 5, 4.


Se observă că în şirul ordonat topologic nodurile se găsesc în ordinea
descrescătoare a timpilor lor t2.
Dacă redesenăm graful cu nodurile aşezate crescător topologic, toate arcele
trebuie să fie în acelaşi sens (de la cel mai mic nod la cel mai mare din punct de
vedere topologic) aşa cum se poate observa şi în figura 2.37.

Fig. 2.37

Exemplu Aplicăm algoritmul de sortare topologică pe digraful fără circuite


din figura 2.38.

Fig. 2.38

Iniţial nodul sursă poate fi 1 sau 6 pentru că ρ⁻(1) = ρ⁻(6) = 0. Presupunem


că se selectează s =1.
După iniţializări avem: U = {2, 3, 4, 5, 6}, V = {1}, W = Ø, t = 1, t1 = (1, ∞,
∞, ∞, ∞, ∞), t2 = (∞, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 2)∈ A, 2 ∈ U, obţinem U = {3, 4, 5, 6}, V = {1, 2}, t = 2, t1 = (1, 2, ∞, ∞, ∞,
∞).

66
Iteraţia 2: Cel mai nou nod din V este x = 2. Avem (2, 3)∈ A, 3∈ U,
obţinem U = {4, 5, 6}, V = {1, 2, 3}, t = 3, t1 = (1, 2, 3, ∞, ∞, ∞).
Iteraţia 3: Se selectează cel mai nou nod din V. Acesta este nodul x = 3,
care nu are succesori. Deci, se efectuează V = {1, 2}, W = {3}, t = 4, t2 = (∞, ∞,
4, ∞, ∞, ∞).
Iteraţia 4: Cel mai nou nod din V este x = 2, care nu are succesori nevizitaţi.
Obţinem V = {1}, W = {3, 2}, t = 5, t2 = (∞, 5, 4, ∞, ∞, ∞).
Iteraţia 5: Se selectează nodul x = 1, fiind singurul nod din V. Se efectuează
V = Ø, W = {3, 2, 1}, t = 6, t2 = (6, 5, 4, ∞, ∞, ∞). Se selectează nodul sursă s = 6
pentru că ρ⁻(6) = 0. Se efectuează U = {4, 5}, V = {6}, t = 7, t1 = (1, 2, 3, ∞, ∞,
7).
Iteraţia 6: Se selectează nodul x = 6. Deoarece (6, 4)∈ A, 4∈ U, obţinem U
= {5}, V = {6, 4}, t = 8, t1 = (1, 2, 3, 8, ∞, 7).
Iteraţia 7: Cel mai nou nod din V este x = 4. Deoarece (4, 5)∈ A, 5∈ U,
obţinem U = Ø, V = {6, 4, 5}, t = 9, t1 = (1, 2, 3, 8, 9, 7).
Iteraţia 8: Cel mai nou nod din V este x = 5. Fiindcă nu mai există noduri
nevizitate, se efectuează V = {6, 4}, W = {3, 2, 1, 5}, t = 10, t2 = (6, 5, 4, ∞, 10,
∞).
Iteraţia 9: Se selectează nodul x = 4. Obţinem V = {6}, W = {3, 2, 1, 5, 4},
t = 11, t2 = (6, 5, 4, 11, 10, ∞).
Iteraţia 10: Singurul nod din V este x =1. Se efectuează V = Ø, W = {3, 2, 1,
5, 4, 6}, t = 12, t2 = (6, 5, 4, 11, 10, 12) şi algoritmul se termină.

Extrăgând nodurile din stiva W, le obţinem sortate topologic: 6, 4, 5, 1, 2,


3. Se observă că în şirul ordonat topologic nodurile se găsesc în ordinea
descrescătoare a timpilor lor t2.
Redesenând graful cu nodurile aşezate crescător topologic atunci obţinem
graful din figura 2.39, în care toate arcele sunt în acelaşi sens, dinspre cel mai
mic spre cel mai mare nod din punct de vedere topologic.

Fig. 2.39

67
La începutul algoritmului existau două noduri care puteau fi alese ca
nod sursă: 1 şi 6. Deci, sortarea topologică a nodurilor grafului din figura 2.38, pe
care am obţinut-o în exemplul 2.18 alegând nodul 1 ca nod sursă, nu este unică.
Dacă am fi început execuţia algoritmului de sortare topologică din nodul
sursă s =6 am fi obţinut următoarea ordine a nodurilor: 1, 6, 4, 5, 2, 3. În figura
2.40 am redesenat graful din figura 2.38, aşezând nodurile în ordinea specificată
mai sus.

Fig. 2.40

M2.U4.6. Rezumat
În acestă unitate de învăţare am prezentat trei aplicaţii ale parcurgerii în
adâncime a unui graf: determinarea componentelor conexe ale unui graf orientat sau
neorientat, determinarea componentelor tare conexe ale unui digraf şi sortarea
topologică a unui digraf fără circuite.
Algoritmul de determinare a componentelor conexe ale unui graf poate fi
obţinut, pornind de la oricare dintre algoritmii de parcurgere. Însă, în vederea unei
abordări unitare a aplicaţiilor parcurgerilor, am folosit, ca punct de plecare, pentru
algoritmul de determinare a componentelor conexe tot algoritmul de parcurgere în
adâncime.

M2.U4.7. Test de evaluare a cunoştinţelor

1. Determinaţi componentele conexe ale următorului graf:

68
2. Determinaţi componentele tare conexe ale următorului graf:

3. Sortaţi topologic următorul digraf:

Temă de control

1. Aplicaţi algoritmul de parcurgere generică totală pe următorul digraf:

2. Aplicaţi algoritmul de parcurgere totală în lăţime pe următorul digraf:

69
3. Aplicaţi algoritmul de parcurgere totală în adâncime pe următorul digraf:

4. Determinaţi componentele conexe ale următorului graf:

5. Determinaţi componentele tare conexe ale următorului graf:

6. Sortaţi topologic următorul digraf:

70
Modulul 2. Parcurgeri de grafuri

Cuprins
Introducere .................................................................................................................... 20
Obiectivele modului ...................................................................................................... 20
U1. Parcurgerea generică ............................................................................................. 21
U2. Parcurgerea în lăţime ............................................................................................. 33
U3. Parcurgerea în adâncime ........................................................................................ 43
U4. Aplicaţii ale parcurgerilor ...................................................................................... 56

Introducere
În acest modul ne vom ocupa de problema parcurgerii unui digraf. Acestă
problemă constă în determinarea tuturor nodurilor accesibile dintr-un nod dat,
numit nod sursă. Problema parcurgerii unui graf poate apărea ca problemă de sine
stătătoare, dar şi ca subproblemă a unei probleme mai complexe.
Vom prezenta mai întâi parcurgerea generică, iar apoi cele mai cunoscute
implementări ale acesteia: parcurgerea în lăţime şi parcurgerea în adâncime. În
finalul modulului, ne vom îndrepta atenţia asupra următoarelor aplicaţii ale
parcurgerilor: determinarea componentelor conexe, determinarea componentelor
tare conexe şi sortarea topologică.

Competenţe
La sfârşitul acestui modul studenţii vor fi capabili să:
 Parcurgă grafuri;
 Determine componentele conexe ale unui graf orientat sau neorientat;
 Determine componentele tare conexe ale unui graf orientat;
 Sorteze topologic un digraf fără circuite.

20
Unitatea de învăţare M2.U1. Parcurgerea generică

Cuprins
M2.U1.1. Introducere .................................................................................................... 21
M2.U1.2. Obiectivele unităţii de învăţare ..................................................................... 22
M2.U1.3. Algoritmul de parcurgere generică ............................................................... 22
M2.U1.4. Algoritmul de parcurgere totală generică ..................................................... 27
M2.U1.5. Rezumat ........................................................................................................ 31
M2.U1.6. Test de evaluare a cunoştinţelor ................................................................... 31

M2.U1.1. Introducere
Problema parcurgerii unui digraf G = (N, A) constă în generarea mulţimii W
a nodurilor y accesibile dintr-un nod sursă dat s. Spunem că nodul y este accesibil
din nodul s în digraful G dacă există drum de la nodul sursă s la nodul y. Evident,
W ⊆ N.
Algoritmii pe care îi vom prezenta în acest modul pentru rezolvarea
problemei parcurgerii unui digraf G sunt metode sistematice de vizitare a nodurilor
y accesibile dintr-un nod sursă dat s. Fiecare iteraţie a execuţiei oricărui algoritm
de parcurgere stabileşte pentru fiecare nod apartenenţa la una din următoarele trei
stări:
• nevizitat,
• vizitat şi neanalizat, adică un nod vizitat ai cărui succesori au fost parţial
vizitaţi,
• vizitat şi analizat, adică un nod vizitat ai cărui succesori au fost în
totalitate vizitaţi.

Dacă nodul x este vizitat şi neanalizat, dacă există arc (x, y) şi dacă nodul y
este nevizitat, atunci se poate vizita nodul y. În acest caz se spune că arcul (x, y)
este arc admisibil şi dacă nodul y este vizitat explorând arcul (x, y) se spune că
nodul x este predecesorul-parcurgere al nodului y.
În acest modul se vor prezenta următorii algoritmi pentru parcurgerea unui
digraf: algoritmul generic de parcurgere, algoritmul de parcurgere în lăţime şi
algoritmul de parcurgere în adâncime. Aceşti algoritmi utilizează următoarele
notaţii comune:

21
U mulţimea nodurilor nevizitate;
V mulţimea nodurilor vizitate şi neanalizate;
W mulţimea nodurilor vizitate şi analizate;
p tabloul predecesor, care este unidimensional cu n elemente.

M2.U1.2. Obiectivele unităţii de învăţare


Această unitate de învăţare îşi propune ca obiectiv principal însuşirea de
către studenţi a algoritmilor de parcurgere generică a grafurilor.
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
 parcurgă un digraf, folosind algoritmul de parcurgere generică.

Durata medie de parcurgere a primei unităţi de învăţare este de 3 ore.

M2.U1.3. Algoritmul de parcurgere generică

Se folosesc notaţiile precizate mai sus şi în plus notăm cu o tabloul ordine care este
unidimensional şi are n elemente.
Algoritmul parcurgerii generice (algoritmul PG) este următorul:
algoritm PG;
begin
U = N – {s}; V = {s}; W = Ø;
for y∈ N do p(y) = 0;
k = 1; o(s) = 1;
for y∈ U do o(y) = ∞;
while V ≠ Ø do
begin
se selectează un nod x din V;
if există arc (x, y)∈ A şi y∈ U then
begin
U = U – {y}; V = V ∪ {y}; p(y) = x; k = k+1; o(y) = k;

22
end
else
begin
V = V – {x}; W = W ∪ {x};
end;
end;
end.

Teoremă. Algoritmul PG are complexitatea O(m).

Definiţie. Un digraf G = (N, A) se numeşte arborescenţă cu rădăcina s dacă este fără


cicluri şi ρ⁻(s) = 0, ρ⁻(x) = 1 pentru toate nodurile x din N cu x ≠ s.

Definiţie. Subgraful Gp = (Np, Ap) cu Np = {y∈ N | p(y)≠0} ∪ {s} şi Ap = {(p(y), y) | y∈


Np -{s}} se numeşte subgraf predecesor al digrafului G = (N, A). Dacă Np = W şi Gp este o
arborescenţă atunci Gp se numeşte arborescenţă parcurgere generică. Arcele din Ap se
numesc arce arborescenţă.

Teoremă. Algoritmul PG determină elementele tabloului p astfel încât subgraful


predecesor Gp = (Np, Ap) este o arborescenţă parcurgere generică.

Drumul de la nodul sursă s la un nod oarecare y se determină, folosind vectorul


predecesor p, cu următoarea procedură:

procedura drum(s, y, p);


begin
if y = s then se tipăreşte s;
else if p(y) = 0 then se tipăreşte "nu există drum de la " + s + " la " + y;
else
begin
drum(s, p(y), p);
se tipăreşte y;
end;

23
end;

Exemplu. Aplicăm algoritmul generic de parcurgere pe digraful din figura


2.1.

Fig. 2.1

După iniţializări avem: s=1, U = {2, 3, 4, 5}, V = {1}, W = Ø, p = (0, 0, 0,


0, 0), k = 1, o = (1, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selecteză x = 1 (nodul 1 fiind singurul nod din V). Avem
(1, 2)∈ A, 2∈ U, deci U = {3, 4, 5}, V = {1, 2}, p = (0, 1, 0, 0, 0), k = 2, o = (1, 2,
∞, ∞, ∞).
Iteraţia 2: Nodul x poate fi oricare dintre nodurile din V. Presupunem că a
fost ales nodul x = 1. Deoarece (1, 3)∈ A, 3∈ U, rezultă U = {4, 5}, V = {1, 2, 3},
p = (0, 1, 1, 0, 0), k = 3, o = (1, 2, 3, ∞, ∞).
Iteraţia 3: Nodul x poate fi oricare dintre nodurile din V. Dacă se selectează
nodul x = 3, cum (3, 5)∈ A, 5∈ U, rezultă U = {4}, V = {1, 2, 3, 5}, p = (0, 1, 1,
0, 3), k = 4, o = (1, 2, 3, ∞, 4).
Iteraţia 4: Presupunem că a fost selectat nodul x = 1 din V. Deoarece nu
există arc de la nodul 1 la un nod nevizitat, înseamnă că nodul 1 este vizitat şi
analizat, deci V = {2, 3, 5}, W = {1}.
Iteraţia 5: Dacă se selectează nodul x = 3 din V, atunci V = {2, 5}, W = {1,
3}.
Iteraţia 6: Dacă se selectează nodul x = 2, cum (2, 4)∈ A, 4∈ U, rezultă U =
Ø, V = {2, 4,5}, p = (0, 1, 1, 2, 3), k = 5, o = (1, 2, 3, 5, 4).
Iteraţia 7: Considerăm că se selectează nodul x = 2 din V. Deoarece nu mai
sunt noduri nevizitate rezultă că V = {4, 5}, W = {1, 2, 3}.
Iteraţia 8: Presupunem că se selectează nodul x = 5 din V, atunci V = {4},

24
W = {1, 2, 3, 5}.
Iteraţia 9: Se selectează nodul x = 4 din V. Obţinem V = Ø, W = {1, 2, 3, 4,
5} şi algoritmul se termină.

La terminarea parcurgerii, p = (0, 1, 1, 2, 3), o = (1, 2, 3, 5, 4) şi W = N,


ceea ce însemnă că toate nodurile digrafului sunt accesibile din nodul sursă s = 1.
Cu ajutorul vectorului predecesor p, determinăm arborescenţa parcurgere
generică din figura 2.2.

Fig. 2.2

Datorită faptului că algoritmul generic de parcurgere nu specifică nicio regulă de


selectare a nodului vizitat şi neanalizat x din care se continuă procesul de vizitare a nodurilor
nevizitate, l-am ales “aleator” pe x. De aceea, acest rezultat al parcurgerii nu este singurul
rezultat corect. Alegând alte noduri x din V decât cele alese în exemplul anterior se vor obţine
alţi vectori o şi/sau p. În cazul în care se obţine un alt vector predecesor, evident că se va
determina şi o altă arborescenţă parcurgere generică.

Exemplu. Aplicăm algoritmul generic de parcurgere pe digraful din figura


2.3.

Fig. 2.3

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6}, V = {1}, W = Ø, p = (0, 0,


0, 0, 0, 0), k = 1, o = (1, ∞, ∞, ∞, ∞, ∞).

25
Iteraţia 1: Se selectează x = 1. Avem (1, 2)∈ A, 2∈ U, deci U = {3, 4, 5, 6},
V = {1, 2}, p = (0, 1, 0, 0, 0, 0), k = 2, o = (1, 2, ∞, ∞, ∞, ∞).
Iteraţia 2: Dacă dintre nodurile vizitate şi neanalizate a fost selectat nodul
x = 2, atunci, deoarece (2, 3)∈ A, 3 ∈ U, obţinem U = {4, 5, 6}, V = {1, 2, 3}, p =
(0, 1, 2, 0, 0, 0), k = 3, o = (1, 2, 3, ∞, ∞, ∞).
Iteraţia 3: Presupunem că se selectează nodul x = 1 din V, atunci V = {2, 3}
şi W = {1}.
Iteraţia 4: Considerăm că se selectează nodul x = 3 din V. Deoarece
(3, 5)∈ A, 5∈ U, obţinem U = {4, 6}, V = {2, 3, 5}, p = (0, 1, 2, 0, 3, 0), k = 4, o
= (1, 2, 3, ∞, 4, ∞).
Iteraţia 5: Presupunem că se selectează nodul x = 2 din V, atunci V = {3, 5}
şi W = {1, 2}.
Iteraţia 6: Considerăm că se selectează nodul x = 5 din V. Rezultă V = {3}
şi W = {1, 2, 5}.
Iteraţia 7: Se selectează x = 3, rezultă V = Ø şi W = {1, 2, 3, 5} şi algoritmul
se termină deoarece nu mai există noduri vizitate şi neanalizate.

La terminarea execuţiei algoritmului, avem p = (0, 1, 2, 0, 3, 0), o = (1, 2,


3, ∞, 4, ∞) şi W = {1, 2, 3, 5}, ceea ce însemnă că nodurile 4 şi 6 nu sunt
accesibile din nodul sursă s = 1. Cu ajutorul vectorului predecesor p, determinăm
arborescenţa parcurgere generică din figura 2.4.

Fig. 2.4

26
M2.U1.4. Algoritmul de parcurgere totală generică

În general, mulţimea W a nodurilor accesibile din nodul sursă dat este o submulţime a
mulţimii nodurilor N. Pentru parcurgerea întregului digraf G = (N, A) se utilizează algoritmul
parcurgerii totale generice (algoritmul PTG) prezentat în continuare.

algoritm PTG;
begin
U = N – {s}; V = {s}; W = Ø;
for y∈ N do p(y) = 0;
k = 1; o(s) = 1;
while W ≠ N do
begin
while V ≠ Ø do
begin
se selectează un nod x din V;
if există arc (x, y)∈ A şi y∈ U then
begin
U = U – {y}; V = V ∪ {y}; p(y) = x; k = k+1; o(y) = k;
end
else
begin
V = V – {x}; W = W ∪ {x};
end;
end;
if U ≠ Ø then
begin
se selectează un nou nod sursă s din U;
U = U – {s}; V = {s}; k = k+1; o(s) = k;
end;
end;
end.

Teoremă Algoritmul PTG are complexitatea O(m).

27
Fie mulţimea S={s | s ∈ N, s este nod sursă selectat la începutul sau pe parcursul
execuţiei algoritmului}.
În parcurgerea totală generică, dacă subgraful predecesor Gp = (Np, Ap) cu Np ={y∈ N |
p(y) ≠ 0} ∪ S, Ap ={(p(y), y) | y∈ Np -S} este o pădure şi Np = W, atunci Gp se numeşte pădure
parcurgere.
Algoritmul PTG determină elementele tabloului p astfel încât subgraful predecesor Gp =
(Np, Ap) este o pădure parcurgere (adică este format din una sau mai multe arborescenţe
parcurgere).

Exemplu. Aplicăm algoritmul generic de parcurgere totală pe digraful din


figura 2.5.

Fig. 2.5

După iniţializări avem: s=1, U = {2, 3, 4}, V = {1}, W = Ø, p = (0, 0, 0,


0), k = 1, o = (1, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 2)∈ A, 2∈ U, obţinem U = {3, 4}, V = {1, 2}, p = (0, 1, 0, 0), k = 2, o = (1, 2,
∞, ∞).
Iteraţia 2: Presupunem că a fost ales nodul x = 1 din V. Deoarece (1, 3)∈ A,
3∈ U, rezultă U = {4}, V = {1, 2, 3}, p = (0, 1, 1, 0), k = 3, o = (1, 2, 3, ∞).
Iteraţia 3: Considerăm că se selectează nodul x = 3. Vom obţine V = {1, 2}
şi W = {3}.
Iteraţia 4: Presupunem că se selectează nodul x = 1 din V. Deoarece (1, 4)∈
A, 4∈ U, rezultă U = Ø, V = {1, 2, 4}, p = (0, 1, 1, 1), k = 4, o = (1, 2, 3, 4).
Iteraţia 5: Dacă se selectează nodul x = 4 din V, atunci V = {1, 2} şi W = {3,

28
4}.
Iteraţia 6: Considerăm că se selectează nodul x = 2. Vom obţine V = {1} şi
W = {2, 3, 4}.
Iteraţia 7: Se selectează nodul x = 1 din V şi obţinem V = Ø, W = {1, 2, 3,
4} şi algoritmul se termină.

La terminarea parcurgerii, avem p = (0, 1, 1, 1) şi o = (1, 2, 3, 4). Cu


ajutorul vectorului predecesor p, determinăm pădurea parcurgere care este
formată dintr-o singură arborescenţă, reprezentată în figura 2.6.

Fig. 2.6

Exemplu. Aplicăm algoritmul generic de parcurgere totală pe digraful din


figura 2.7.

Fig. 2.7

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6}, V = {1}, W = Ø, p = (0, 0,


0, 0, 0, 0), k = 1, o = (1, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează x = 1. Deoarece (1, 2)∈ A, 2∈ U, obţinem U = {3,
4, 5, 6}, V = {1, 2}, p = (0, 1, 0, 0, 0, 0), k = 2, o = (1, 2, ∞, ∞, ∞, ∞).
Iteraţia 2: Dacă dintre nodurile vizitate şi neanalizate a fost selectat nodul

29
x = 2, atunci, deoarece (2, 3)∈ A, 3 ∈ U, obţinem U = {4, 5, 6}, V = {1, 2, 3}, p =
(0, 1, 2, 0, 0, 0), k = 3, o = (1, 2, 3, ∞, ∞, ∞).
Iteraţia 3: Presupunem că se selectează nodul x = 1 din V, atunci V = {2, 3}
şi W = {1}.
Iteraţia 4: Considerăm că se selectează nodul x = 3 din V. Deoarece
(3, 5)∈ A, 5∈ U, obţinem U = {4, 6}, V = {2, 3, 5}, p = (0, 1, 2, 0, 3, 0), k = 4, o
= (1, 2, 3, ∞, 4, ∞).
Iteraţia 5: Presupunem că se selectează nodul x = 2 din V, atunci V = {3, 5}
şi W = {1, 2}.
Iteraţia 6: Considerăm că se selectează nodul x = 5 din V. Rezultă V = {3}
şi W = {1, 2, 5}.
Iteraţia 7: Se selectează x = 3, rezultă V = Ø şi W = {1, 2, 3, 5} şi, deoarece
nu mai există noduri vizitate şi neanalizate, algoritmul va selecta un nou nod
sursă dintre nodurile încă nevizitate. Fie acesta nodul 4. Deci, s = 4, U = {6}, V =
{4}, k = 5 şi o = (1, 2, 3, 5, 4, ∞).
Iteraţia 8: Se selectează x = 4. Deoarece (4, 6)∈ A, 6∈ U, obţinem U = Ø, V
= {4, 6}, p = (0, 1, 2, 0, 3, 4), k = 6, o = (1, 2, 3, 5, 4, 6).
Iteraţia 9: Considerăm că se selectează nodul x = 4 din V. Rezultă V = {6}
şi W = {1, 2, 3, 4, 5}.
Iteraţia 10: Se selectează x = 6, rezultă V = Ø şi W = {1, 2, 3, 4, 5, 6} şi
algoritmul se termină.

La finalul algoritmului, avem p = (0, 1, 2, 0, 3, 4) şi o = (1, 2, 3, 5, 4, 6).


Deoarece au existat două noduri sursă (nodul 1 şi nodul 4), se va obţine, cu
ajutorul vectorului predecesor p, o pădure parcurgere formată din două
arborescenţe parcurgere (una cu rădăcina 1 şi cealaltă cu rădăcina 4), care sunt
reprezentate în figura 2.8.

30
Fig. 2.8

M2.U1.5. Rezumat
Algoritmii de parcurgere a unui graf sunt metode sistematice de vizitare a
nodurilor grafului, pornind dintr-un nod sursă. În cazul algoritmului generic de
parcurgere (totală) nodul din care se continuă parcurgerea este selectat, fără nicio
regulă, dintre nodurile vizitate şi neanalizate.

M2.U1.6. Test de evaluare a cunoştinţelor

1. Aplicaţi algoritmul de parcurgere generică pe următorul digraf:

2. Aplicaţi algoritmul de parcurgere generică totală pe următorul digraf:

31
Unitatea de învăţare M2.U2. Parcurgerea în lăţime

Cuprins
M2.U2.1. Introducere .................................................................................................... 32
M2.U2.2. Obiectivele unităţii de învăţare ..................................................................... 32
M2.U2.3. Parcurgerea în lăţime .................................................................................... 33
M2.U2.4. Parcurgerea totală în lăţime .......................................................................... 37
M2.U2.5. Rezumat ........................................................................................................ 41
M2.U2.6. Test de evaluare a cunoştinţelor ................................................................... 41

M2.U2.1. Introducere

Algoritmul generic de parcurgere (totală) nu specifică nicio regulă de


selectare a nodului vizitat şi neanalizat x din care se continuă vizitarea nodurilor.
Impunând diferite reguli de selectare a nodului x, se obţin diferiţi algoritmi de
parcurgere a unui digraf G = (N, A). Cei mai utilizaţi algoritmi de parcurgere sunt:
• parcurgerea în lăţime, în engleză breadth first (BF),
• parcurgerea în adâncime, în engleză depth first (DF).

M2.U2.2. Obiectivele unităţii de învăţare


Această unitate de învăţare îşi propune ca obiectiv principal însuşirea de
către studenţi a algoritmilor de parcurgere în lăţime a grafurilor.
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
 parcurgă un digraf, folosind algoritmul de parcurgere în lăţime.

Durata medie de parcurgere a acestei unităţi de învăţare este de 3 ore.

32
M2.U2.3. Parcurgerea în lăţime

Fie digraful G =(N, A) cu nodul sursă s şi ∆x mulţimea drumurilor de la nodul sursă s la


nodul x∈ N. Numărul de arce care compun un drum Dx∈ ∆x defineşte lungimea acestui drum
pe care o notăm cu l(Dx). Distanţa de la nodul s la nodul x se defineşte în modul următor:

min{l ( Dx ) | Dx ∈ ∆ x }, daca ∆ x ≠ ∅

d ( x) = 
 ∞, daca ∆ x = ∅

Un drum Dx∈ ∆x cu l(Dx) = d(x) se numeşte cel mai scurt drum de la nodul sursă s la
nodul x.
În algoritmul parcurgerii BF (algoritmul PBF) se folosesc aceleaşi notaţii ca în
algoritmul PG cu deosebirea că în locul tabloului ordine o se utilizează tabloul lungime l care
este unidimensional şi are n elemente. Mulţimea nodurilor vizitate şi neanalizate V este
organizată, ca structură de date, ca o coadă. Algoritmul PBF este următorul:

algoritm PBF;
begin
U = N – {s}; V = {s}; W = Ø;
for y∈ N do p(y) = 0;
l(s) = 0;
for y∈ U do l(y) = ∞;
while V ≠ Ø do
begin
se selectează cel mai vechi nod x introdus în V;
for (x, y)∈ A do
if y∈ U then
begin
U = U – {y}; V = V ∪ {y}; p(y) = x; l(y) = l(x) + 1;
end
V = V – {x}; W = W ∪ {x};
end;
end.

33
Teoremă. Algoritmul PBF are complexitatea O(m).

În parcurgerea BF, dacă Np =W şi subgraful predecesor Gp = (Np, Ap) este o


arborescenţă atunci Gp se numeşte arborescenţă parcurgere BF.

Teoremă. Algoritmul PBF determină:


a) elementele tabloului l astfel încât l(y) = d(y) pentru y∈ N.
b) elementele tabloului p astfel încât subgraful predecesor Gp = (Np, Ap) este o
arborescenţă parcurgere BF

Exemplu
Aplicăm algoritmul de parcurgere în lăţime pe digraful din figura 2.9.

Fig. 2.9

Deoarece mulţimea V trebuie organizată ca o coadă, vom scrie la sfârşitul


ei nodurile nou adăugate şi vom extrage întotdeauna primul nod din V.

După iniţializări avem: s=1, U = {2, 3, 4, 5}, V = {1}, W = Ø, p = (0, 0, 0,


0, 0), l = (0, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1. Deoarece (1, 2)∈ A şi 2∈ U, obţinem
U = {3, 4, 5}, V = {1, 2}, p = (0, 1, 0, 0, 0), l = (0, 1, ∞, ∞, ∞). Avem (1, 3)∈ A şi
3∈ U, deci U = {4, 5}, V = {1, 2, 3}, p = (0, 1, 1, 0, 0), l = (0, 1, 1, ∞, ∞). Cum
(1, 5)∈ A şi 5∈ U, obţinem U = {4}, V = {1, 2, 3, 5}, p = (0, 1, 1, 0, 1), l = (0, 1,
1, ∞, 1). Se actualizează mulţimile V şi W: V = {2, 3, 5} şi W = {1}.
Iteraţia 2: Se selectează cel mai vechi nod din V, acesta este x = 2.
Deoarece nu există succesori nevizitaţi ai nodului 2, se efectuează V = {3, 5} şi W
= {1, 2}.
Iteraţia 3: Cel mai vechi nod din V este x = 3. Deoarece (3, 4)∈ A şi 4∈ U,
obţinem U = Ø, V = {3, 5, 4}, p = (0, 1, 1, 3, 1), l = (0, 1, 1, 2, 1). Se fac

34
actualizările: V = {5, 4} şi W = {1, 2, 3}.
Iteraţia 4: Se selectează cel mai vechi nod din V, acesta este x = 5.
Deoarece nu mai există noduri nevizitate, se efectuează V = {4} şi W = {1, 2, 3,
5}.
Iteraţia 5: Se selectează nodul x = 4. Obţinem V = Ø, W = {1, 2, 3, 4, 5} şi
algoritmul se termină.

După parcurgerea în lăţime am obţinut, p = (0, 1, 1, 3, 1), l = (0, 1, 1, 2, 1)


şi W = N, ceea ce înseamnă că toate nodurile digrafului sunt accesibile din nodul
sursă s = 1. Cu ajutorul vectorului predecesor p, determinăm arborescenţa
parcurgere BF, care este reprezentată în figura 2.10.

Fig. 2.10

Evident, drumul unic de la s = 1 la orice nod y∈ Np din arborescenţa


parcurgere BF este un cel mai scurt drum de la s la y în digraful G = (N, A).

Exemplu. Aplicăm algoritmul de parcurgere în lăţime pe digraful din


figura 2.11.

Fig. 2.11

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6, 7}, V = {1}, W = Ø, p = (0,

35
0, 0, 0, 0, 0, 0), l = (0, ∞, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1. Deoarece (1, 2)∈ A şi 2∈ U, obţinem
U = {3, 4, 5, 6, 7}, V = {1, 2}, p = (0, 1, 0, 0, 0, 0, 0), l = (0, 1, ∞, ∞, ∞, ∞, ∞).
Avem (1, 5)∈ A şi 5 ∈ U, deci U = {3, 4, 6, 7}, V = {1, 2, 5}, p = (0, 1, 0, 0, 1, 0,
0), l = (0, 1, ∞, ∞, 1, ∞, ∞). Cum (1, 6)∈ A şi 6 ∈ U, obţinem U = {3, 4, 7}, V =
{1, 2, 5, 6}, p = (0, 1, 0, 0, 1, 1, 0), l = (0, 1, ∞, ∞, 1, 1, ∞). Se actualizează
mulţimile V şi W: V = {2, 5, 6} şi W = {1}.
Iteraţia 2: Se selectează cel mai vechi nod din V, acesta este x = 2.
Deoarece nu există succesori nevizitaţi ai nodului 2, se efectuează V = {5, 6} şi W
= {1, 2}.
Iteraţia 3: Cel mai vechi nod din V este x = 5. Deoarece (5, 3)∈ A şi 3∈ U,
obţinem U = {4, 7}, V = {5, 6, 3}, p = (0, 1, 5, 0, 1, 1, 0), l = (0, 1, 2, ∞, 1, 1, ∞).
Se fac actualizările: V = {6, 3} şi W = {1, 2, 5}.
Iteraţia 4: Se selectează cel mai vechi nod din V, acesta este x = 6.
Deoarece nodul 6 nu are succesori nevizitaţi, se efectuează V = {3} şi W = {1, 2,
5, 6}.
Iteraţia 5: Se selectează nodul x = 3. Obţinem V = Ø, W = {1, 2, 3, 5, 6} şi
algoritmul se termină.

La sfârşitul algoritmlui de parcurgere în lăţime am obţinut, p = (0, 1, 5, 0,


1, 1, 0), l = (0, 1, 2, ∞, 1, 1, ∞) şi W = {1, 2, 3, 5, 6}, ceea ce înseamnă că
nodurile 4 şi 7 nu sunt accesibile din nodul sursă s = 1. Cu ajutorul vectorului
predecesor p, determinăm arborescenţa parcurgere BF, care este reprezentată în
figura 2.12.

Fig. 2.12

36
M2.U2.4. Parcurgerea totală în lăţime

Observaţie. În general, mulţimea W a nodurilor accesibile din nodul sursă dat este o
submulţime a mulţimii nodurilor N. Pentru parcurgerea în lăţime a întregului digraf G = (N,
A) se utilizează algoritmul parcurgerii totale în lăţime (algoritmul PTBF), care este următorul:

algoritm PTBF;
begin
U = N – {s}; V = {s}; W = Ø;
for y∈ N do p(y) = 0;
l(s) = 0;
while W ≠ N do
begin
while V ≠ Ø do
begin
se selectează cel mai vechi nod x introdus în V;
for (x, y)∈ A do
if y∈ U then
begin
U = U – {y}; V = V ∪ {y}; p(y) = x; l(y) = l(x) + 1;
end
V = V – {x}; W = W ∪ {x};
end;
if U ≠ Ø then
begin
se selectează un nou nod sursă s din U;
U = U – {s}; V = {s}; l(s) = 0;
end;
end;
end.

37
Fie mulţimea S={s | s ∈ N, s este nod sursă selectat la începutul sau pe parcursul
execuţiei algoritmului}.
În parcurgerea totală BF, dacă subgraful predecesor Gp = (Np, Ap) cu Np = {y∈ N |
p(y) ≠ 0} ∪ S, Ap ={(p(y), y) | y∈ Np -S} este o pădure şi Np = W, atunci Gp se numeşte pădure
parcurgere BF.
Algoritmul PTBF determină elementele tabloului p astfel încât subgraful predecesor Gp
= (Np, Ap) este o pădure parcurgere BF.

Exemplu Aplicăm algoritmul de parcurgere totală în lăţime pe digraful din


figura 2.13.

Fig. 2.13

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6}, V = {1}, W = Ø, p = (0, 0,


0, 0, 0, 0), l = (0, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1. Deoarece (1, 2)∈ A şi 2∈ U, obţinem
U = {3, 4, 5, 6}, V = {1, 2}, p = (0, 1, 0, 0, 0, 0), l = (0, 1, ∞, ∞, ∞, ∞). Avem (1,
3)∈ A şi 3 ∈ U, deci U = {4, 5, 6}, V = {1, 2, 3}, p = (0, 1, 1, 0, 0, 0), l = (0, 1, 1,
∞, ∞, ∞). Se actualizează mulţimile V şi W: V = {2, 3} şi W = {1}.
Iteraţia 2: Se selectează cel mai vechi nod din V, acesta este x = 2.
Deoarece (2, 4)∈ A şi 4∈ U, obţinem U = {5, 6}, V = {2, 3, 4}, p = (0, 1, 1, 2, 0,
0), l = (0, 1, 1, 2, ∞, ∞). Avem (2, 5)∈ A şi 5∈ U, deci U = {6}, V = {2, 3, 4, 5},
p = (0, 1, 1, 2, 2, 0), l = (0, 1, 1, 2, 2, ∞). Se efectuează V = {3, 4, 5} şi W = {1,
2}.
Iteraţia 3: Cel mai vechi nod din V este x = 3. Dar nodul 3 nu are succesori
nevizitaţi, deci V = {4, 5} şi W = {1, 2, 3}.
Iteraţia 4: Se selectează cel mai vechi nod din V, acesta este x = 4. Avem
(4, 6)∈ A şi 6∈ U, deci U = Ø, V = {4, 5, 6}, p = (0, 1, 1, 2, 2, 4), l = (0, 1, 1, 2, 2,
3). Se efectuează V = {5, 6} şi W = {1, 2, 3, 4}.
Iteraţia 5: Se selectează nodul x = 5, care este cel mai vechi nod din V.

38
Deoarece nu mai există noduri nevizitate, se efectuează V = {6} şi W = {1, 2, 3,
4, 5}.
Iteraţia 6: Se selectează nodul x = 6. Se efectuează V = Ø, W = {1, 2, 3, 4,
5, 6} şi algoritmul se termină.

Deoarece toate nodurile au fost vizitate pornind din nodul sursă s = 1 (nu a
fost necesar să selectăm noi noduri sursă) rezultatul parcurgerii totale în lăţime ar
fi putut fi obţinut şi cu algoritmul de parcurgere în lăţime. Deci, s-a obţinut o
singură arborescenţa parcurgere BF, care este reprezentată în figura 2.14.

Fig. 2.14

Exemplu Aplicăm algoritmul de parcurgere totală în lăţime pe digraful din


figura 2.15.

Fig. 2.15

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6, 7}, V = {1}, W = Ø, p = (0,


0, 0, 0, 0, 0, 0), l = (0, ∞, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1. Deoarece (1, 2)∈ A şi 2∈ U, obţinem
U = {3, 4, 5, 6, 7}, V = {1, 2}, p = (0, 1, 0, 0, 0, 0, 0), l = (0, 1, ∞, ∞, ∞, ∞, ∞).
Avem (1, 5)∈ A şi 5 ∈ U, deci U = {3, 4, 6, 7}, V = {1, 2, 5}, p = (0, 1, 0, 0, 1, 0,
0), l = (0, 1, ∞, ∞, 1, ∞, ∞). Se actualizează mulţimile V şi W: V = {2, 5} şi W =
{1}.

39
Iteraţia 2: Se selectează cel mai vechi nod din V, acesta este x = 2.
Deoarece nodul 2 nu are succesori, se efectuează V = {5} şi W = {1, 2}.
Iteraţia 3: Cel mai vechi nod din V este x = 5. Deoarece nici nodul 5 nu are
succesori nevizitaţi, obţinem V = Ø şi W = {1, 2, 5}. Se determină un nou nod
sursă dintre nodurile nevizitate (din U). Fie acesta s = 3. Se fac actualizările U =
{4, 6, 7}, V = {3}, l = (0, 1, 0, ∞, 1, ∞, ∞).
Iteraţia 4: Se selectează singurul nod din V, acesta este x = 3. Deoarece
nodul 3 nu are succesori nevizitaţi, se efectuează V = Ø şi W = {1, 2, 3, 5}. Se
determină un nou nod sursă dintre nodurile nevizitate. Fie acesta s = 4. Se fac
actualizările U = {6, 7}, V = {4}, l = (0, 1, 0, 0, 1, ∞, ∞).
Iteraţia 5: Se selectează nodul x = 4. Deoarece (4, 6)∈ A şi 6∈ U, obţinem
U = {7}, V = {4, 6}, p = (0, 1, 0, 0, 1, 4, 0), l = (0, 1, 0, 0, 1, 1, ∞). Avem (4, 7)∈
A şi 7∈ U, deci U = Ø, V = {4, 6, 7}, p = (0, 1, 0, 0, 1, 4, 4), l = (0, 1, 0, 0, 1, 1,
1). Se actualizează mulţimile V şi W: V = {6, 7} şi W = {1, 2, 3, 4, 5}.
Iteraţia 6: Cel mai vechi nod din V este x = 6. Deoarece nu mai sunt noduri
nevizitate, obţinem V = {7} şi W = {1, 2, 3, 4, 5, 6}.
Iteraţia 7: Singurul nod din V este x = 7. Se efectuează V = Ø, W = {1, 2, 3,
4, 5, 6, 7} şi algoritmul se termină.

La sfârşitul algoritmlui de parcurgere totală în lăţime am obţinut, p = (0, 1,


0, 0, 1, 4, 4), l = (0, 1, 0, 0, 1, 1, 1). Cu ajutorul vectorului predecesor p,
determinăm pădurea parcurgere BF formată din cele trei arborescenţe care au ca
noduri rădăcină nodurile sursă selectate în algoritm (nodurile 1, 3 şi 4) şi care
sunt reprezentate în figura 2.16.

Fig. 2.16

40
M2.U2.5. Rezumat
Algoritmul de parcurgere (totală) în lăţime a unui graf este o metodă
sistematică de vizitare a nodurilor grafului, pornind dintr-un nod sursă. Întotdeauna
nodul din care se continuă parcurgerea este cel mai vechi dintre nodurile vizitate şi
neanalizate. Deci, putem obţine algoritmul de parcurgere (totală) în lăţime
organizând ca o coadă a mulţimea V a nodurilor vizitate şi neanalizate din algoritmul
generic de parcurgere (totală).

M2.U2.6. Test de evaluare a cunoştinţelor

1. Aplicaţi algoritmul de parcurgere în lăţime pe următorul digraf:

2. Aplicaţi algoritmul de parcurgere totală în lăţime pe următorul digraf:

41
Unitatea de învăţare M2.U3. Parcurgerea în adâncime

Cuprins
M2.U3.1. Introducere .................................................................................................... 42
M2.U3.2. Obiectivele unităţii de învăţare ..................................................................... 42
M2.U3.3. Parcurgerea în adâncime............................................................................... 43
M2.U3.4. Parcurgerea totală în adâncime ..................................................................... 47
M2.U3.5. Rezumat ........................................................................................................ 54
M2.U3.6. Test de evaluare a cunoştinţelor ................................................................... 54

M2.U3.1. Introducere

Una dintre cele mai des utilizate implementări ale algoritmului generic de
parcurgere (totală) este algoritmul de parcurgere (totală) în adâncime. Acesta
constă, după cum numele său sugerează, în a vizita cât mai “adânc” graful. Pentru
aceasta, la fiecare pas, se continua parcurgerea din ultimul nod vizitat, dacă el are
măcar un successor nevizitat, iar, în caz contrar, se revine la nodul din care el a
fost vizitat.

M2.U3.2. Obiectivele unităţii de învăţare


Această unitate de învăţare îşi propune ca obiectiv principal însuşirea de
către studenţi a algoritmilor de parcurgere în adâncime a grafurilor.
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
 parcurgă un digraf, folosind algoritmul de parcurgere în adâncime.

Durata medie de parcurgere a acestei unităţi de învăţare este de 3 ore.

42
M2.U3.3. Parcurgerea în adâncime

În algoritmul de parcurgere în adâncime (algoritmul PDF) se folosesc aceleaşi notaţii ca


în algoritmul PG cu deosebirea că în locul tabloului unidimensional ordine o se utilizează
tablourile timp unidimensionale t1 şi t2 care au fiecare n elemente. În t1(x) se reţine momentul
când x devine nod vizitat şi neanalizat, iar în t2(x) momentul când x devine nod vizitat şi
analizat, x∈ N. Mulţimea nodurilor vizitate şi neanalizate V este organizată, ca structură de
date, ca o stivă.
Algoritmul PDF este următorul:

algoritm PDF;
begin
U = N – {s}; V = {s}; W = Ø;
for y∈ N do p(y) = 0;
t = 1; t1(s) = 1;
for y∈ U do
begin
t1(y) = ∞; t2(y) = ∞;
end;
while V ≠ Ø do
begin
se selectează cel mai nou nod x introdus în V;
if există arc (x,y)∈ A şi y∈ U then
begin
U = U – {y}; V = V ∪ {y}; p(y) = x; t = t +1;t1(y)= t;
end
else
begin
V = V – {x}; W = W ∪ {x}; t = t +1; t2(x)= t;
end;
end;
end.

Teoremă Algoritmul PDF are complexitatea O(m).

43
În parcurgerea DF, dacă Np =W şi subgraful predecesor Gp = (Np, Ap) este o arborescenţă
atunci Gp se numeşte arborescenţă parcurgere DF.

Exemplu Aplicăm algoritmul de parcurgere în adâncime pe digraful din


figura 2.17.
Deoarece mulţimea V trebuie organizată ca o stivă, vom scrie la sfârşitul ei
nodurile nou adăugate şi vom extrage întotdeauna ultimul nod din V.
După iniţializări avem: s=1, U = {2, 3, 4}, V = {1}, W = Ø, p = (0, 0, 0,
0), t = 1, t1 = (1, ∞, ∞, ∞), t2 = (∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 2)∈ A, 2∈ U, obţinem U = {3, 4}, V = {1, 2}, p = (0, 1, 0, 0), t = 2, t1 = (1, 2,
∞, ∞).

Fig. 2.17

Iteraţia 2: Cel mai nou nod din V este x = 2. Avem (2, 3)∈ A, 3∈ U,
obţinem U = {4}, V = {1, 2, 3}, p = (0, 1, 2, 0), t = 3, t1 = (1, 2, 3, ∞).
Iteraţia 3: Se selectează cel mai nou nod din V, acesta este x = 3. Deoarece
nodul 3 nu are succesori nevizitaţi, se efectuează V = {1, 2}, W = {3}, t = 4, t2 =
(∞, ∞, 4, ∞).
Iteraţia 4: Cel mai nou nod din V este x = 2. Avem (2, 4)∈ A, 4∈ U,
obţinem U = Ø, V = {1, 2, 4}, p = (0, 1, 2, 2), t = 5, t1 = (1, 2, 3, 5).
Iteraţia 5: Se selectează cel mai nou nod din V, acesta este x = 4. Deoarece
nu mai există noduri nevizitate, se efectuează V = {1, 2}, W = {3, 4}, t = 6, t2 =
(∞, ∞, 4, 6).
Iteraţia 6: Cel mai nou nod din V este x = 2. Se fac actualizările: V = {1},
W = {2, 3, 4}, t = 7, t2 = (∞, 7, 4, 6).

44
Iteraţia 7: Se selectează x = 1. Se efectuează V = Ø, W = {1, 2, 3, 4}, t = 8,
t2 = (8, 7, 4, 6) şi algoritmul se termină.

Fig. 2.18

La finalul algoritmului am obţinut W = {1, 2, 3, 4} (deci toate nodurile


digrafului sunt accesibile din nodul 1), vectorii timp t1 = (1, 2, 3, 5) şi t2 = (8, 7,
4, 6) şi vectorul predecesor p = (0, 1, 2, 2), cu ajutorul căruia determinăm
arborescenţa parcurgere DF ilustrată în figura 2.18.

Exemplu Aplicăm algoritmul de parcurgere în adâncime pe digraful din


figura 2.19.

Fig. 2.19

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6}, V = {1}, W = Ø, p = (0, 0,


0, 0, 0, 0), t = 1, t1 = (1, ∞, ∞, ∞, ∞, ∞), t2 = (∞, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 2)∈ A, 2∈ U, obţinem U = {3, 4, 5, 6}, V = {1, 2}, p = (0, 1, 0, 0, 0, 0), t = 2,
t1 = (1, 2, ∞, ∞, ∞, ∞).
Iteraţia 2: Cel mai nou nod din V este x = 2. Avem (2, 3)∈ A, 3∈ U,
obţinem U = {4, 5, 6}, V = {1, 2, 3}, p = (0, 1, 2, 0, 0, 0), t = 3, t1 = (1, 2, 3, ∞, ∞,

45
∞).
Iteraţia 3: Se selectează cel mai nou nod din V. Acesta este nodul x = 3.
Deoarece (3, 4)∈ A, 4∈ U, obţinem U = {5, 6}, V = {1, 2, 3, 4}, p = (0, 1, 2, 3, 0,
0), t = 4, t1 = (1, 2, 3, 4, ∞, ∞).
Iteraţia 4: Cel mai nou nod din V este x = 4. Avem (4, 5)∈ A, 5∈ U,
obţinem U = {6}, V = {1, 2, 3, 4, 5}, p = (0, 1, 2, 3, 4, 0), t = 5, t1 = (1, 2, 3, 4, 5,
∞).
Iteraţia 5: Se selectează cel mai nou nod din V. Acesta este nodul x = 5.
Deoarece nodul 5 nu are succesori, se efectuează V = {1, 2, 3, 4}, W = {5}, t = 6,
t2 = (∞, ∞, ∞, ∞, 6, ∞).
Iteraţia 6: Se selectează cel mai nou nod din V. Acesta este nodul x = 4.
Deoarece nodul 4 nu are succesori nevizitaţi, se efectuează V = {1, 2, 3}, W = {4,
5}, t = 7, t2 = (∞, ∞, ∞, 7, 6, ∞).
Iteraţia 7: Cel mai nou nod din V este x = 3. Obţinem V = {1, 2}, W = {3, 4,
5}, t = 8, t2 = (∞, ∞, 8, 7, 6, ∞).
Iteraţia 8: Se selectează cel mai nou nod din V. Acesta este nodul x = 2. Se
efectuează V = {1}, W = {2, 3, 4, 5}, t = 9, t2 = (∞, 9, 8, 7, 6, ∞).
Iteraţia 9: Singurul nod din V este x = 1. Obţinem V = Ø, W = {1, 2, 3, 4,
5}, t = 10, t2 = (10, 9, 8, 7, 6, ∞) şi algoritmul se termină.

La sfârşitul algoritmului am obţinut W = {1, 2, 3, 4, 5}, ceea ce înseamnă


că doar nodul 6 nu este accesibil din nodul sursă 1, vectorii timp t1 = (1, 2, 3, 4, 5,
∞) şi t2 = (10, 9, 8, 7, 6, ∞). Cu ajutorul vectorului predecesor p = (0, 1, 2, 3, 4, 0)
determinăm arborescenţa parcurgere DF ilustrată în figura 2.20.

46
Fig. 2.20

M2.U3.4. Parcurgerea totală în adâncime

Aşa cum se observă şi din exemplul anterior, în general, mulţimea W a nodurilor


accesibile din nodul sursă dat este o submulţime a mulţimii nodurilor N. Pentru parcurgerea în
adâncime a întregului digraf G = (N, A) se utilizează algoritmul parcurgerii totale în adâncime
(algoritmul PTDF), care este următorul:

algoritm PTDF;
begin
U = N – {s}; V = {s}; W = Ø;
for y∈ N do p(y) = 0;
t = 1; t1(s) = 1;
while W ≠ N do
begin
while V ≠ Ø do
begin
se selectează cel mai nou nod x introdus în V;

47
if există arc (x,y)∈ A şi y∈ U then
begin
U = U – {y}; V = V ∪ {y}; p(y) = x; t = t +1;t1(y)= t;
end
else
begin
V = V – {x}; W = W ∪ {x}; t = t +1; t2(x)= t;
end;
end;
if U ≠ Ø then
begin
se selectează un nou nod sursă s din U;
U = U – {s}; V = {s}; t = t+ 1; t1(s) = t;
end;
end;
end.

Teoremă Algoritmul PTDF are complexitatea O(m).

Fie mulţimea S={s | s ∈ N, s este nod sursă selectat la începutul sau pe parcursul
execuţiei algoritmului}.
În parcurgerea totală DF, dacă subgraful predecesor Gp = (Np, Ap) cu Np = {y∈ N |
p(y) ≠ 0} ∪ S, Ap ={(p(y), y) | y∈ Np -S} este o pădure şi Np = W, atunci Gp se numeşte pădure
parcurgere DF.
Algoritmul PTDF determină elementele tabloului p astfel încât subgraful predecesor Gp
= (Np, Ap) este o pădure parcurgere DF.
Parcurgerea totală DF poate fi utilizată la clasificarea arcelor digrafului G = (N, A) în
raport cu pădurea parcurgere DF. În această clasificare există două clase de arce:
• arce arborescenţă,
• arce nonarborescenţă.

Mulţimea arcelor arborescenţă, notată P, este P = Ap. Aceste arce introduc, în timpul
parcurgerii totale DF a digrafului G = (N, A), noduri în mulţimea nodurilor vizitate şi

48
neanalizate V. Mulţimea arcelor nonarborescenţă, notată P , este P = A – Ap. Clasa arcelor

nonarborescenţă P este alcătuită din trei subclase:


• arce de înaintare,
• arce de revenire,
• arce de traversare.

Mulţimea arcelor de înaintare, notată I, este alcătuită din acele arce (x, y) pentru care
nodul x este un ascendent al nodului y în pădurea parcurgere DF. Mulţimea arcelor de
revenire, notată R, este alcătuită din acele arce (x, y) pentru care nodul x este un descendent al
nodului y în pădurea parcurgere DF. Mulţimea arcelor de traversare, notată T, este alcătuită
din acele arce (x, y) pentru care nodul x nu este nici ascendent, nici descendent al nodului y în
pădurea parcurgere DF. Aceste trei mulţimi de arce nonarborescenţă sunt disjuncte două câte

două şi P = I ∪ R ∪ T .

Teoremă. Într-o parcurgere totală DF a unui digraf G = (N, A), arcul (x, y) este:
(1) un arc arborescenţă sau de înaintare dacă şi numai dacă t1(x) < t1(y) < t2(y) < t2(x);
(2) un arc de revenire dacă şi numai dacă t1(y) < t1(x) < t2(x) < t2(y);
(3) un arc de traversare dacă şi numai dacă t1(y) < t2(y) < t1(x) < t2(x).

Exemplu Aplicăm algoritmul de parcurgere totală în adâncime pe digraful


din figura 2.21.

Fig. 2.21

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6}, V = {1}, W = Ø, p = (0, 0,


0, 0, 0, 0), t = 1, t1 = (1, ∞, ∞, ∞, ∞, ∞), t2 = (∞, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 2)∈ A, 2∈ U, obţinem U = {3, 4, 5, 6}, V = {1, 2}, p = (0, 1, 0, 0, 0, 0), t = 2,
t1 = (1, 2, ∞, ∞, ∞, ∞).
Iteraţia 2: Cel mai nou nod din V este x = 2. Avem (2, 3)∈ A, 3∈ U, rezultă

49
că U = {4, 5, 6}, V = {1, 2, 3}, p = (0, 1, 2, 0, 0, 0), t = 3, t1 = (1, 2, 3, ∞, ∞, ∞).
Iteraţia 3: Se selectează cel mai nou nod din V. Acesta este nodul x = 3.
Deoarece (3, 4)∈ A, 4∈ U, obţinem U = {5, 6}, V = {1, 2, 3, 4}, p = (0, 1, 2, 3, 0,
0), t = 4, t1 = (1, 2, 3, 4, ∞, ∞).
Iteraţia 4: Cel mai nou nod din V este x = 4. Avem (4, 5)∈ A, 5∈ U,
obţinem U = {6}, V = {1, 2, 3, 4, 5}, p = (0, 1, 2, 3, 4, 0), t = 5, t1 = (1, 2, 3, 4, 5,
∞).
Iteraţia 5: Se selectează cel mai nou nod din V. Acesta este nodul x = 5.
Deoarece nodul 5 nu are succesori, se efectuează V = {1, 2, 3, 4}, W = {5}, t = 6,
t2 = (∞, ∞, ∞, ∞, 6, ∞).
Iteraţia 6: Se selectează cel mai nou nod din V. Acesta este nodul x = 4.
Avem (4, 6)∈ A, 6∈ U, rezultă că U = Ø, V = {1, 2, 3, 4, 6}, p = (0, 1, 2, 3, 4, 4),
t = 7, t1 = (1, 2, 3, 4, 5, 7).
Iteraţia 7: Cel mai nou nod din V este x = 6. Deoarece nu mai sunt noduri
nevizitate, obţinem V = {1, 2, 3, 4}, W = {5, 6}, t = 8, t2 = (∞, ∞, ∞, ∞, 6, 8).
Iteraţia 8: Se selectează cel mai nou nod din V. Acesta este nodul x = 4. Se
efectuează V = {1, 2, 3}, W = {4, 5, 6}, t = 9, t2 = (∞, ∞, ∞, 9, 6, 8).
Iteraţia 9: Cel mai nou nod din V este x = 3. Obţinem V = {1, 2}, W = {3, 4,
5, 6}, t = 10, t2 = (∞, ∞, 10, 9, 6, 8).
Iteraţia 10: Se selectează cel mai nou nod din V. Acesta este nodul x = 2. Se
efectuează V = {1}, W = {2, 3, 4, 5, 6}, t = 11, t2 = (∞, 11, 10, 9, 6, 8).
Iteraţia 11: Singurul nod din V este x = 1. Obţinem V = Ø, W = {1, 2, 3, 4,
5, 6}, t = 12, t2 = (12, 11, 10, 9, 6, 8) şi algoritmul se termină.

50
Fig. 2.22

La sfârşitul algoritmului, p = (0, 1, 2, 3, 4, 4), t1 = (1, 2, 3, 4, 5, 7) şi t2 =


(12, 11, 10, 9, 6, 8). Cu ajutorul vectorului predecesor p, determinăm pădurea
parcurgere DF reprezentată în figura 2.22.

Cu ajutorul vectorilor timp t1 şi t2, clasificăm arcele aşa cum se vede în


figura 2.23, unde pe fiecare arc am trecut mulţimea căreia îi aparţine.

Fig. 2.23

Exemplu
Aplicăm algoritmul de parcurgere totală în adâncime pe digraful din figura
2.24.

51
Fig. 2.24

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6, 7}, V = {1}, W = Ø, p = (0,


0, 0, 0, 0, 0, 0), t = 1, t1 = (1, ∞, ∞, ∞, ∞, ∞, ∞), t2 = (∞, ∞, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 2)∈ A, 2∈ U, obţinem U = {3, 4, 5, 6, 7}, V = {1, 2}, p = (0, 1, 0, 0, 0, 0, 0),
t = 2, t1 = (1, 2, ∞, ∞, ∞, ∞, ∞).
Iteraţia 2: Cel mai nou nod din V este x = 2. Avem (2, 5)∈ A, 5∈ U,
obţinem U = {3, 4, 6, 7}, V = {1, 2, 5}, p = (0, 1, 0, 0, 2, 0, 0), t = 3, t1 = (1, 2, ∞,
∞, 3, ∞, ∞).
Iteraţia 3: Se selectează cel mai nou nod din V. Acesta este nodul x = 5.
Deoarece nodul 5 nu are succesori, se efectuează V = {1, 2}, W = {5}, t = 4, t2 =
(∞, ∞, ∞, ∞, 4, ∞, ∞).
Iteraţia 4: Cel mai nou nod din V este x = 2, care nu are succesori nevizitaţi.
Deci, V = {1}, W = {2, 5}, t = 5, t2 = (∞, 5, ∞, ∞, 4, ∞, ∞).
Iteraţia 5: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 3)∈ A, 3∈ U, obţinem U = {4, 6, 7}, V = {1, 3}, p = (0, 1, 1, 0, 2, 0, 0), t = 6,
t1 = (1, 2, 6, ∞, 3, ∞, ∞).
Iteraţia 6: Cel mai nou nod din V este x =3. Deoarece (3, 4)∈ A, 4∈ U,
obţinem U = {6, 7}, V = {1, 3, 4}, p = (0, 1, 1, 3, 2, 0, 0), t = 7, t1 = (1, 2, 6, 7, 3,
∞, ∞).
Iteraţia 7: Cel mai nou nod din V este x = 4. Deoarece nodul 4 nu are
succesori nevizitaţi, obţinem V = {1, 3}, W = {2, 4, 5}, t = 8, t2 = (∞, 5, ∞, 8, 4,
∞, ∞).
Iteraţia 8: Se selectează x = 3. Deci, V = {1}, W = {2, 3, 4, 5}, t = 9, t2 = (∞,
5, 9, 8, 4, ∞, ∞).
Iteraţia 9: Singurul nod din V este x = 1. Obţinem V = Ø, W = {1, 2, 3, 4,
5}, t = 10, t2 = (10, 5, 9, 8, 4, ∞, ∞). Având noduri nevizitate, selectăm o nouă

52
sursă. Fie aceasta s = 6. Se efectuează U = {7}, V = {6}, t = 11, t1 = (1, 2, 6, 7, 3,
11, ∞).
Iteraţia 10: Se selectează nodul x = 6, fiind singurul nod din V. Deoarece
(6, 7)∈ A, 7∈ U, obţinem U = Ø, V = {6, 7}, p = (0, 1, 1, 3, 2, 0, 6), t = 12, t1 =
(1, 2, 6, 7, 3, 11, 12).
Iteraţia 11: Cel mai nou nod din V este x = 7. Deoarece nu mai sunt noduri
nevizitate, obţinem V = {6}, W = {1, 2, 3, 4, 5, 7}, t = 13, t2 = (10, 5, 9, 8, 4, ∞,
13).
Iteraţia 12: Singurul nod din V este x = 6. Obţinem V = Ø, W = {1, 2, 3, 4,
5, 6, 7}, t = 14, t2 = (10, 5, 9, 8, 4, 14, 13) şi algoritmul se termină.

Fig. 2.25

La sfârşitul algoritmului, p = (0, 1, 1, 3, 2, 0, 6), t1 = (1, 2, 6, 7, 3, 11, 12) şi


t2 = (10, 5, 9, 8, 4, 14, 13). Cu ajutorul vectorului predecesor p, determinăm
pădurea parcurgere DF reprezentată în figura 2.25.
Cu ajutorul vectorilor timp t1 şi t2, clasificăm arcele aşa cum se vede în
figura 2.26, unde pe fiecare arc am trecut mulţimea căreia îi aparţine.

Fig. 2.26

53
M2.U3.5. Rezumat
Algoritmul de parcurgere (totală) în adâncime a unui graf este o metodă
sistematică de vizitare a nodurilor grafului, pornind dintr-un nod sursă. Întotdeauna
nodul din care se continuă parcurgerea este cel mai nou dintre nodurile vizitate şi
neanalizate. Deci, putem obţine algoritmul de parcurgere (totală) în adâncime
organizând ca o stivă a mulţimea V a nodurilor vizitate şi neanalizate din algoritmul
generic de parcurgere (totală).

M2.U3.6. Test de evaluare a cunoştinţelor

1. Aplicaţi algoritmul de parcurgere în adâncime pe următorul digraf:

2. Aplicaţi algoritmul de parcurgere totală în adâncime pe următorul digraf:

54
Unitatea de învăţare M2.U4. Aplicaţii ale parcurgerilor

Cuprins
M2.U4.1. Introducere .................................................................................................... 55
M2.U4.2. Obiectivele unităţii de învăţare ..................................................................... 55
M2.U4.3. Determinarea componentelor conexe ........................................................... 56
M2.U4.4. Determinarea componentelor tare conexe .................................................... 60
M2.U4.5. Sortarea topologică ....................................................................................... 64
M2.U4.6. Rezumat ........................................................................................................ 68
M2.U4.7. Test de evaluare a cunoştinţelor ................................................................... 68

M2.U4.1. Introducere

Problema parcurgerii unui graf poate apărea ca problemă de sine stătătoare


sau ca subproblemă a unei alet probleme. De exemplu, pentru a determina
componentele tare conexe ale unui digraf, este necesară parcurgerea lui în
adâncime. De asemenea, algoritmul de parcurgere în adâncime poate fi modificat
uşor pentru a sorta topologic un digraf fără circuite.
Algoritmul de determinare a componentelor conexe ale unui graf poate fi
obţinut, pornind de la oricare dintre algoritmii de parcurgere. Însă, în vederea unei
abordări unitare a aplicaţiilor parcurgerilor, vom folosi ca punct de plecare tot
algoritmul de parcurgere în adâncime.

M2.U4.2. Obiectivele unităţii de învăţare


Această unitate de învăţare îşi propune ca obiectiv principal însuşirea de
către studenţi a noţiunilor de conexitate, tare conexitate şi sortare topologică.
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
 Determine componenetele conexe ale unui graf;
 Determine componenetele tare conexe ale unui graf;.
 Sorteze topologic un digraf fără circuite.

55
Durata medie de parcurgere a primei unităţi de învăţare este de 3 ore.

M2.U4.3. Determinarea componentelor conexe

Un digraf G = (N, A) se numeşte slab conex sau conex dacă pentru oricare două noduri
diferite x, y există un lanţ care are aceste două noduri drept extremităţi.
Noţiunea de conexitate are sens şi pentru grafuri neorientate.
Se numeşte componentă conexă a unui digraf G = (N, A) un subgraf G´ = (N´, A´) al lui
G, care este conex şi care este maximal în raport cu incluziunea faţă de această proprietate
(oricare ar fi x∈ N - N´, subgraful G x′ generat de N ′x = N´ ∪ {x} nu este conex).

O componentă conexă G´ = (N´, A´) a unui digraf G = (N, A) se poate identifica prin
mulţimea N´ care generează subgraful G´.
Deoarece în problema conexităţii sensul arcelor nu contează, algoritmul va fi descris
pentru grafuri neorientate. Dacă G = (N, A) este digraf atunci i se asociază graful neorientat

Gˆ = ( Nˆ , Aˆ ) , unde N̂ = N, Â ={[x, y]| (x, y) ∈ A sau (y, x) ∈ A}. Este evident că G = (N, A)

şi Gˆ = ( Nˆ , A
ˆ ) au aceleaşi componente conexe (privite ca mulţimi de noduri).
Algoritmul de deteminare a componentelor conexe (algoritmul CC) este o adaptare a
algoritmului PTDF aplicat unui graf neorientat G = (N, A). Nu se calculează tablourile timp t1,
t2 şi nici vectorul predecesor p, în mulţimea N´ reţinem componenta conexă curentă, iar la
sfârşitul algoritmului nc va fi numărul de componte conexe ale grafului. Algoritmul CC este
următorul:

algoritm CC;
begin
U = N – {s}; V = {s}; W = Ø; nc = 1; N' = {s};
while W ≠ N do
begin
while V ≠ Ø do
begin
se selectează cel mai nou nod x introdus în V;

56
if există muchie [x, y]∈ A şi y∈ U then
begin
U = U – {y}; V = V ∪ {y}; N´ = N´ ∪ {y};
end
else
begin
V = V – {x}; W = W ∪ {x};
end;
end;
se tipăresc nc şi N´;
if U ≠ Ø then
begin
se selectează un nou nod sursă s din U;
U = U – {s}; V = {s}; nc = nc+ 1; N´ = {s};
end;
end;
end.

Teoremă Algoritmul CC are complexitatea O(m).

Exemplu Aplicăm algoritmul de determinare a componentelor conexe pe


graful neorientat din figura 2.27.

După iniţializări avem: s=1, U = {2, 3, 4}, V = {1}, W = Ø, N´= {1}, nc =


1.
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
[1, 3]∈ A, 3∈ U, obţinem U = {2, 4}, V = {1, 3}, N´= {1, 3}.
Iteraţia 2: Cel mai nou nod din V este x = 3. Avem [3, 2]∈ A, 2∈ U,
obţinem U = {4}, V = {1, 3, 2}, N´= {1, 2, 3}.

57
Fig. 2.27

Iteraţia 3: Se selectează cel mai nou nod din V. Acesta este nodul x = 2.
Deoarece [2, 4]∈ A, 4∈ U, obţinem U = Ø, V = {1, 3, 2, 4}, N´= {1, 2, 3, 4}.
Iteraţia 4: Cel mai nou nod din V este x = 4. Deoarece nu mai sunt noduri
nevizitate, obţinem V = {1, 3, 2}, W = {4}.
Iteraţia 5: Se selectează cel mai nou nod din V. Acesta este nodul x = 2. Se
efectuează V = {1, 3}, W = {2, 4}.
Iteraţia 6: Cel mai nou nod din V este x = 3. Deci, V = {1}, W = {2, 3, 4}.
Iteraţia 7: Se selectează nodul x = 1. Se efectuează V = Ø, W = {1, 2, 3, 4},
se tipăresc nc=1 şi N´= {1, 2, 3, 4} şi algoritmul se termină.

Deoarece la sfârşitul algoritmului nc=1 înseamnă că graful este conex.

58
Exemplu Pentru a determina componentele conexe ale digrafului din figura
2.28, trebuie mai întâi să determinăm graful neorientat corespunzător lui. Acesta
este reprezentat în figura 2.29.

Fig. 2.28

Fig. 2.29

După iniţializări avem: s=1, U = {2, 3, 4, 5, 6, 7}, V = {1}, W = Ø, N´=


{1}, nc = 1.
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
[1, 2]∈ A, 2∈ U, obţinem U = {3, 4, 5, 6, 7}, V = {1, 2}, N´= {1, 2}.
Iteraţia 2: Cel mai nou nod din V este x = 2. Avem [2, 5]∈ A, 5∈ U,
obţinem U = {3, 4, 6, 7}, V = {1, 2, 5}, N´= {1, 2, 5}.
Iteraţia 3: Se selectează cel mai nou nod din V. Acesta este nodul x = 5.
Deoarece nodul 5 nu are vecini nevizitaţi, se efectuează V = {1, 2}, W = {5}.
Iteraţia 4: Cel mai nou nod din V este x = 2. Obţinem V = {1}, W = {2, 5}.
Iteraţia 5: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
[1, 3]∈ A, 3∈ U, obţinem U = {4, 6, 7}, V = {1, 3}, N´= {1, 2, 3, 5}.
Iteraţia 6: Cel mai nou nod din V este x =3. Deoarece nodul 3 nu are vecini
nevizitaţi, se efectuează V = {1}, W = {2, 3, 5}.
Iteraţia 7: Singurul nod din V este x = 1. Se efectuează V = Ø, W = {1, 2, 3,
5}, se tipăresc nc=1 şi N´= {1, 2, 3, 5}. Deoarece există noduri nevizitate,
selectăm o nouă sursă. Fie aceasta s = 4. Se efectuează U = {6, 7}, V = {4}, nc =

59
2, N´= {4}.
Iteraţia 8: Se selectează x = 4. Fiindcă [4, 6]∈ A, 6∈ U, obţinem U = {7},
V = {4, 6}, N´= {4, 6}.
Iteraţia 9: Cel mai nou nod din V este x = 6. Avem [6, 7]∈ A, 7∈ U,
obţinem U = Ø, V = {4, 6, 7}, N´= {4, 6, 7}.
Iteraţia 10: Se selectează cel mai nou nod din V. Acesta este nodul x = 7.
Deoarece nodul nu mai există noduri nevizitate, se efectuează V = {4, 6}, W = {1,
2, 3, 5, 7}.
Iteraţia 11: Cel mai nou nod din V este x = 6. Obţinem V = {4}, W = {1, 2,
3, 5, 6, 7}.
Iteraţia 12: Singurul nod din V este x = 4. Obţinem V = Ø, W = {1, 2, 3, 4,
5, 6, 7}, se tipăresc nc=2 şi N´= {4, 6, 7} şi algoritmul se termină.

Deci, digraful din figura 2.28 nu este conex, are două componente conexe:
{1, 2, 3, 5} şi {4, 6, 7}. Evident, aceste afirmaţii sunt adevărate şi pentru graful
neorientat din figura 2.29.

M2.U4.4. Determinarea componentelor tare conexe

Un digraf G = (N, A) se numeşte tare conex dacă pentru oricare două noduri diferite x, y
există un drum de la x la y şi un drum de la y la x.
Evident, noţiunea de tare conexitate are sens numai pentru digrafuri.

Se numeşte componentă tare conexă a unui digraf G = (N, A) un subgraf G´ = (N´, A´)
al lui G, care este tare conex şi care este maximal în raport cu incluziunea faţă de această
proprietate (oricare ar fi x∈ N - N´, subgraful G x′ generat de N ′x = N´ ∪ {x} nu este tare
conex).
O componentă tare conexă G´ = (N´, A´) a unui digraf G = (N, A) se poate identifica cu
mulţimea N´ care generează subgraful G´.
Algoritmul de determinare a componentelor tare conexe (algoritmul CTC) este
următorul:

60
algoritm CTC;
begin
se aplică digrafului G algoritmul PTDF pentru a determina vectorul t2;
se determină G-1 graful invers al digrafului G;
se aplică digrafului invers G-1 algoritmul PTDF modificat în modul următor:
nodul sursă s este ales astfel încât t2(s) ≥ t2(x) pentru orice nod nevizitat x, unde t2 este
vectorul timp determinat cu algoritmul PTDF aplicat digrafului G.
se determină componentele tare conexe ale lui G după regula: nodurile care
sunt în aceeaşi arborescenţă DF a digrafului G-1 formează o componentă tare conexă a
lui G.
end.

Teoremă Complexitatea algoritmului CTC este O(m).

Se numeşte digraf condensat asociat digrafului G = (N, A) digraful Ĝ =( N̂ , Â ), N̂

={N1,…,Nq}, Â ={(Ni, Nj) | Ni, Nj∈ N̂ şi există (x, y)∈ A cu x∈ Ni, y∈ Nj}, unde N1,…,Nq
sunt componentele tare conexe ale digrafului G= (N, A).

Exemplu Aplicăm algoritmul de determinare a componentelor tare conexe


pe digraful din figura 2.30.

Fig. 2.30

Aplicând algoritmul PTDF obţinem t2 = (12, 11, 10, 9, 6, 8).


Graful invers al digrafului din figura 2.30 este reprezentat în figura 2.31.

61
Fig. 2.31

Parcurgerea totală DF a grafului invers se începe din nodul sursă s =1


pentru că nodul 1 are cel mai mare timp t2. Nodurile accesibile din nodul 1 în
digraful invers sunt: 1, 2, 3, 4 şi 6. Acestea vor forma prima componentă tare
conexă a digrafului din figura 2.30. Singurul nod rămas nevizitat este nodul 5,
care va constitui cea de-a doua componentă tare conexă a digrafului iniţial. Deci,
digraful nu este tare conex, el având două componente tare conexe {1, 2, 3, 4, 6}
şi {5}.
Digraful condensat este reprezentat în figura 2.32.

Fig. 2.32

Exemplu Aplicăm algoritmul de determinare a componentelor tare conexe


pe digraful din figura 2.33.

Fig. 2.33

Aplicând algoritmul PTDF obţinem t2 = (10, 9, 8, 7, 6, 14, 13).


Se determină graful invers al digrafului din figura 2.33, care este

62
reprezentat în figura 2.34.

Fig. 2.34

Parcurgerea totală DF a grafului invers se începe din nodul sursă s =6,


deoarece el a fost ultimul nod vizitat şi analizat în parcurgerea totală DF a
digrafului iniţial. Nodurile accessibile din 6 sunt 6 şi 7, deci ele formează prima
componentă tare conexă a digrafului iniţial.
Se alege ca nodul sursă nodul 1 deoarece are cel mai mare timp t2 dintre
nodurile rămase nevizitate (1, 2, 3, 4, 5). Din nodul 1 nu se mai poate vizita
niciun alt nod, deci el va forma a doua componentă tare conexă a digrafului din
figura 2.33.
Se selectează s = 2 pentru că nodul 2 are cel mai mare timp t2 dintre
nodurile rămase nevizitate (2, 3, 4, 5). Nodurile accesibile din 2, care sunt 2, 3 şi
4 formează a treia componentă tare conexă.
Singurul nod rămas nevizitat este nodul 5, care va constitui a patra
componentă tare conexă a digrafului iniţial. Deci, componentele tare conexe ale
digrafului din figura 2.33 sunt {1}, {2, 3, 4}, {5} şi {6, 7}, iar corespunzător lor
am obţinut digraful condensat din figura 2.35.

Fig. 2.35

63
M2.U4.5. Sortarea topologică

Sortarea topologică a unui digraf G = (N, A) fără circuite constă în ordonarea nodurilor
din N după regula:
dacă (x, y) ∈ A atunci x < y.
Digrafurile fără circuite sunt folosite în multe aplicaţii pentru a indica relaţia de
anterioritate dintre anumite evenimente.
O modalitate de testare a existenţei circuitelor întrun digraf este dată de următoarea
teoremă.

Teoremă Un digraf G = (N, A) este fără circuite dacă şi numai dacă orice parcurgere
totală DF a lui G nu produce arce de revenire.

Algoritmul sortare topologică (algoritmul ST) se obţine din algoritmul PTDF cu


următoarele modificări:

(1) nodurile sursă s sunt alese astfel încât ρ⁻(s) = 0,

(2) mulţimea W a nodurilor vizitate şi neanalizate este organizată ca o stivă,


(3) nu se mai determină vectorul predecesor p.

La terminarea algoritmului ST, stiva W furnizează sortarea topologică a digrafului G =


(N, A) fără circuite. Se observă că sortarea topologică a nodurilor coincide cu aranjarea lor în
ordinea descrescătoare a timpilor t2 determinaţi cu algoritmul PTDF.

64
Exemplu Aplicăm algoritmul de sortare topologică pe digraful fără circuite
din figura 2.36.

Deoarece mulţimea W trebuie organizată ca o stivă, vom scrie la sfârşitul ei


nodurile nou adăugate.

Fig. 2.36

Iniţial nodul sursă va fi s=1 pentru că ρ⁻(1) = 0.


După iniţializări avem: U = {2, 3, 4, 5}, V = {1}, W = Ø, t = 1, t1 = (1, ∞,
∞, ∞, ∞), t2 = (∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 2)∈ A, 2∈ U, obţinem U = {3, 4, 5}, V = {1, 2}, t = 2, t1 = (1, 2, ∞, ∞, ∞).
Iteraţia 2: Cel mai nou nod din V este x = 2. Avem (2, 4)∈ A, 4∈ U,
obţinem U = {3, 5}, V = {1, 2, 4}, t = 3, t1 = (1, 2, ∞, 3, ∞).
Iteraţia 3: Se selectează cel mai nou nod din V. Acesta este nodul x = 4.
Deoarece nodul 4 nu are succesori, se efectuează V = {1, 2}, W = {4}, t = 4, t2 =
(∞, ∞, ∞, 4, ∞).
Iteraţia 4: Cel mai nou nod din V este x = 2. Avem (2, 5)∈ A, 5∈ U,
obţinem U = {3}, V = {1, 2, 5}, t = 5, t1 = (1, 2, ∞, 3, 5).
Iteraţia 5: Se selectează cel mai nou nod din V. Acesta este nodul x = 5.
Deoarece nodul 5 nu are succesori nevizitaţi, se efectuează V = {1, 2}, W = {4,
5}, t = 6, t2 = (∞, ∞, ∞, 4, 6).
Iteraţia 6: Cel mai nou nod din V este x = 2, care nu mai are succesori
nevizitaţi, deci V = {1}, W = {4, 5, 2}, t = 7, t2 = (∞, 7, ∞, 4, 6).
Iteraţia 7: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 3)∈ A, 3∈ U, obţinem U = Ø, V = {1, 3}, t = 8, t1 = (1, 2, 8, 3, 5).
Iteraţia 8: Cel mai nou nod din V este x = 3. Fiindcă nu mai există noduri
nevizitate, se efectuează V = {1}, W = {4, 5, 2, 3}, t = 9, t2 = (∞, 7, 9, 4, 6).

65
Iteraţia 9: Se selectează nodul x = 1. Obţinem V = Ø, W = {4, 5, 2, 3, 1}, t =
10, t2 = (10, 7, 9, 4, 6) şi algoritmul se termină.

Extrăgând nodurile din stiva W, le obţinem sortate topologic: 1, 3, 2, 5, 4.


Se observă că în şirul ordonat topologic nodurile se găsesc în ordinea
descrescătoare a timpilor lor t2.
Dacă redesenăm graful cu nodurile aşezate crescător topologic, toate arcele
trebuie să fie în acelaşi sens (de la cel mai mic nod la cel mai mare din punct de
vedere topologic) aşa cum se poate observa şi în figura 2.37.

Fig. 2.37

Exemplu Aplicăm algoritmul de sortare topologică pe digraful fără circuite


din figura 2.38.

Fig. 2.38

Iniţial nodul sursă poate fi 1 sau 6 pentru că ρ⁻(1) = ρ⁻(6) = 0. Presupunem


că se selectează s =1.
După iniţializări avem: U = {2, 3, 4, 5, 6}, V = {1}, W = Ø, t = 1, t1 = (1, ∞,
∞, ∞, ∞, ∞), t2 = (∞, ∞, ∞, ∞, ∞, ∞).
Iteraţia 1: Se selectează nodul x = 1, fiind singurul nod din V. Deoarece
(1, 2)∈ A, 2 ∈ U, obţinem U = {3, 4, 5, 6}, V = {1, 2}, t = 2, t1 = (1, 2, ∞, ∞, ∞,
∞).

66
Iteraţia 2: Cel mai nou nod din V este x = 2. Avem (2, 3)∈ A, 3∈ U,
obţinem U = {4, 5, 6}, V = {1, 2, 3}, t = 3, t1 = (1, 2, 3, ∞, ∞, ∞).
Iteraţia 3: Se selectează cel mai nou nod din V. Acesta este nodul x = 3,
care nu are succesori. Deci, se efectuează V = {1, 2}, W = {3}, t = 4, t2 = (∞, ∞,
4, ∞, ∞, ∞).
Iteraţia 4: Cel mai nou nod din V este x = 2, care nu are succesori nevizitaţi.
Obţinem V = {1}, W = {3, 2}, t = 5, t2 = (∞, 5, 4, ∞, ∞, ∞).
Iteraţia 5: Se selectează nodul x = 1, fiind singurul nod din V. Se efectuează
V = Ø, W = {3, 2, 1}, t = 6, t2 = (6, 5, 4, ∞, ∞, ∞). Se selectează nodul sursă s = 6
pentru că ρ⁻(6) = 0. Se efectuează U = {4, 5}, V = {6}, t = 7, t1 = (1, 2, 3, ∞, ∞,
7).
Iteraţia 6: Se selectează nodul x = 6. Deoarece (6, 4)∈ A, 4∈ U, obţinem U
= {5}, V = {6, 4}, t = 8, t1 = (1, 2, 3, 8, ∞, 7).
Iteraţia 7: Cel mai nou nod din V este x = 4. Deoarece (4, 5)∈ A, 5∈ U,
obţinem U = Ø, V = {6, 4, 5}, t = 9, t1 = (1, 2, 3, 8, 9, 7).
Iteraţia 8: Cel mai nou nod din V este x = 5. Fiindcă nu mai există noduri
nevizitate, se efectuează V = {6, 4}, W = {3, 2, 1, 5}, t = 10, t2 = (6, 5, 4, ∞, 10,
∞).
Iteraţia 9: Se selectează nodul x = 4. Obţinem V = {6}, W = {3, 2, 1, 5, 4},
t = 11, t2 = (6, 5, 4, 11, 10, ∞).
Iteraţia 10: Singurul nod din V este x =1. Se efectuează V = Ø, W = {3, 2, 1,
5, 4, 6}, t = 12, t2 = (6, 5, 4, 11, 10, 12) şi algoritmul se termină.

Extrăgând nodurile din stiva W, le obţinem sortate topologic: 6, 4, 5, 1, 2,


3. Se observă că în şirul ordonat topologic nodurile se găsesc în ordinea
descrescătoare a timpilor lor t2.
Redesenând graful cu nodurile aşezate crescător topologic atunci obţinem
graful din figura 2.39, în care toate arcele sunt în acelaşi sens, dinspre cel mai
mic spre cel mai mare nod din punct de vedere topologic.

Fig. 2.39

67
La începutul algoritmului existau două noduri care puteau fi alese ca
nod sursă: 1 şi 6. Deci, sortarea topologică a nodurilor grafului din figura 2.38, pe
care am obţinut-o în exemplul 2.18 alegând nodul 1 ca nod sursă, nu este unică.
Dacă am fi început execuţia algoritmului de sortare topologică din nodul
sursă s =6 am fi obţinut următoarea ordine a nodurilor: 1, 6, 4, 5, 2, 3. În figura
2.40 am redesenat graful din figura 2.38, aşezând nodurile în ordinea specificată
mai sus.

Fig. 2.40

M2.U4.6. Rezumat
În acestă unitate de învăţare am prezentat trei aplicaţii ale parcurgerii în
adâncime a unui graf: determinarea componentelor conexe ale unui graf orientat sau
neorientat, determinarea componentelor tare conexe ale unui digraf şi sortarea
topologică a unui digraf fără circuite.
Algoritmul de determinare a componentelor conexe ale unui graf poate fi
obţinut, pornind de la oricare dintre algoritmii de parcurgere. Însă, în vederea unei
abordări unitare a aplicaţiilor parcurgerilor, am folosit, ca punct de plecare, pentru
algoritmul de determinare a componentelor conexe tot algoritmul de parcurgere în
adâncime.

M2.U4.7. Test de evaluare a cunoştinţelor

1. Determinaţi componentele conexe ale următorului graf:

68
2. Determinaţi componentele tare conexe ale următorului graf:

3. Sortaţi topologic următorul digraf:

Temă de control

1. Aplicaţi algoritmul de parcurgere generică totală pe următorul digraf:

2. Aplicaţi algoritmul de parcurgere totală în lăţime pe următorul digraf:

69
3. Aplicaţi algoritmul de parcurgere totală în adâncime pe următorul digraf:

4. Determinaţi componentele conexe ale următorului graf:

5. Determinaţi componentele tare conexe ale următorului graf:

6. Sortaţi topologic următorul digraf:

70

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