Download - Curs Grafuri Cristina Flaut
1
Lect. dr. Cristina FLAUT
ALGORITMICA GRAFURILOR
CURS
Specializarea INFORMATICA, anul II 2010
2
CUPRINS Pagina Capitolul 1 Notiuni introductive -Program 1. Program de determinare a vecinilor unui varf intr-un graf neorientat in C++ -Program 2. Program de determinare a vecinilor unui varf intr-un graf orientat in C++
4 4 6
7
Capitolul 2 Drumuri optime intr-un graf
13
-2.1. Matrice asociate unui graf -Program 3. Program de determinare a vecinilor unui varf intr-un graf neorientat in C++
13 14
-2.2. Determinarea matricei drumurilor într-un graf. Determinarea componentelor tare conexe -Algoritmul Roy-Warshall -Program 4. Algoritmul Roy-Warshall --Varianta 1 --Varianta 2 -Program 5. Algoritmul de determinare a componentelor tare conexe implementat in C++ -Algoritmul Malgrange
20
21
22
24 27
28 -2.3. Drumuri optime într-un graf -Algoritmul Roy-Floyd - Program 6. Algoritmul Roy-Floyd implementat in C++ -Algoritmii Dantzing 1+2, -Algoritmul lui Yen -Algoritmul Bellman-Kalaba
35 36 38 46 48 52
Capitolul 3 Probleme Hamiltoniene si Euleriene
56
-Probleme Hamiltoniene 56
3
-Probleme Euleriene 66 Capitolul 4
Retele de transport. Algoritmul Ford-Fulkerson
72
-4.1. Retele de transport 72 -4.2. Algoritmul Ford-Fulkerson. Flux maxim în reţele de transport - Program 7. Algoritmul Ford-Fulkerson implementat in C++ , varianta 1 de etichetare
74
80
-4. 3. Algoritmul Ford-Fulkerson. Flux minim în reţele de transport
85
Capitolul 5 Arbori
87
-Algoritmul Kruskal 89 -Algoritmul Prim - Program 8. Algoritmul Prim, implementat in C++
90 91
-Aplicatii in informatica , 93 -Gramezi 94 Programul 9. Implementarea gramezii in C++ 96 - Probleme de sortare-cautare 98 -Parcurgerea arborilor 99 -Evaluarea expresiilor algebrice 101 Capitolul 6 103 Probleme de colorare Algoritmul lui Zykov 106 Bibliografie 110
4
CAPITOLUL 1
NOŢIUNI INTRODUCTIVE
Teoria grafurilor, la începuturile ei, s-a dezvoltat paralel cu algebra. Grafurile au multiple aplcaţii practice, fiind strâns legate de multe ramuri ale matematicii (cercetări operaţionale, teoria grupurilor, teoria numerelor), dar sunt folosite şi ca modele matematice în rezolvarea unor probleme tehnice, economice, etc. Studiul grafurilor îşi are originea în lucrările lui Euler din 1736, în care studia problema podurilor de la Königsberg. Oraşul Königsberg se află aproape de punctual de vărsare a râului Pregolea în Marea Baltică. Râul are pe teritoriul oraşului două braţe confluente iar în punctual de confluenţă se află o insulă, numită “Curtea Hanului”1. Această insulă este legată de maluri prin cinci poduri. Peste fiecare braţ al râului mai există câte un pod. Problema care a apărut cerea să se găsească un traseu continuu care să treacă o singură dată pe fiecare din cele şapte poduri.(vezi Figura 1.1.) Euler a fost primul care a arătat că această problemă nu are soluţie.
Figura 1.1.
1 H. R. Radian, T. J. Radian, Recreaţii matematice, Editura Albatros, Bucureşti, 1973.
5
Prima carte de teoria grafurilor a fost publicată de D. König în 1936, Theorie der endlichen und unendlichen Grphen, urmată de cartea lui C. Berge în 1957 Théorie des graphes et ses applications.
Fie X o mulţime finită nevidă, X={x1, x2 ,…,xn }. Se numeşte graf o pereche G = (X, U) formată din mulţimea X de vârfuri sau noduri şi din mulţimea U={u1, u2, …, um } de perechi de vârfuri numite arce sau muchii. Reprezentarea grafurilor poate fi făcută în diferite moduri în funcţie de cine este “utilizatorul”. Dacă este calculatorul, este de preferat ca graful să fie dat cu ajutorul matricei sale de adiacenţă. Altfel, oamenii, preferă vizualizarea grafului sub forma unei colecţii de puncte legate prin linii, ceea ce implică darea unor informaţii geometrice despre graf. Cardinalul mulţimii X, se notează |X|, şi se numeşte ordinul grafului G. În cele ce urmează vom lucra numai cu grafuri finite. În mulţimea U putem avea mai multe perechi identice. Dacă numărul lor nu depăşeşte un număr natural q, spunem că G este un q-graf
Un 1-graf se mai numeşte şi graf orientat. În această situaţie U este o submulţime a produsului cartezian XX . Atunci orice element
Uu este o pereche ordonată, de forma ),,( yxu cu Xyx , şi îl numim arc. Vârful x se numeşte extremitatea iniţială iar vărful y se numeşte extremitatea finală. În acest caz vârfurile x şi y se numesc adiacente.
În cazul în care nu tinem cont de orientarea arcelor, atunci (x, y) nu mai este o pereche ordonată. Deci, U va fi formată din submulţimi ale mulţimii X, cu două elemente, {x, y}, sau cu un singur element {x}. În această situaţie ele se vor numi muchii, respectiv bucle.
Dacă graful G nu are bucle şi nu conţine două muchii egale(egalitate ca mulţimi), adică U este o submulţime a mulţimii părţilor mulţimii X, cu două elemente, atunci perechea G = (X, U) se numeşte graf simplu sau neorientat.
Definiţia 1. 1. Fie G = (X, U) un graf , Xx un vârf al său.
i) Mulţimea
}),(/{ UyxXyx
6
se numeşte mulţimea succesorilor vârfului x. Deci orice element y x se numeşte succesor al vârfului x. În cazul grafurilor orientate, x
se numeşte semigradul exterior al vârfului x şi-l notăm cu d+x.
ii) Mulţimea
}),(/{ UxyXyx
se numeşte mulţimea predecesorilor vârfului x. Deci orice element y x se numeşte predecesor al vârfului x. În cazul grafurilor orientate, x se numeşte semigradul interior al vârfului x şi-l notăm cu dx
-.
iii) Mulţimea
xxx
se numeşte mulţimea vecinilor vârfului x sau a vârfurilor adiacente cu vârful x. În cazul grafurilor orientate, dx = d+
x + xd se numeşte gradul
vârfului x. În cazul grafurilor neorientate, gradul unui vârf x este este numărul muchiilor pentru care x este o extremitate, deci:
xxxxx ddd )(21 .
Determinarea vecinilor varfurilor intr-un graf orientat/neorientat,
se poate face si cu ajutorul programului de mai jos dat in C++: Program 1.
//af vecinii unui nod in graf neorientat # include <stdio.h> # include <conio.h> void main(void) { int a[50][50],n,i,j; FILE *f=fopen("intrare2.txt","r"); fscanf(f,"%d",&n); for(i=1;i<=n;i++)
7
for(j=1;j<=n;j++) fscanf(f,"%d",&a[i][j]); fclose(f); for(i=1;i<=n;i++) { printf("\nVecinii vf %d sunt:\n",i); for(j=1;j<=n;j++) if((a[i][j]==1)||(a[j][i]==1)) printf(" %d ",j); } getch(); } Datele sunt puse in fisierul intrare2.txt.
Dupa rularea programului, obtinem:
Program 2. //af vecinii unui nod intr-un graf orientat # include <stdio.h> # include <conio.h>
8
void main(void) { int a[50][50],n,i,j; FILE *f=fopen("intrare1.txt","r"); fscanf(f,"%d",&n); for(i=1;i<=n;i++) for(j=1;j<=n;j++) fscanf(f,"%d",&a[i][j]); fclose(f); for(i=1;i<=n;i++) { printf("\nVecinii vf %d sunt:\n",i); for(j=1;j<=n;j++) if(a[i][j]==1) printf(" %d ",j); } getch(); } Datele sunt puse in fisierul intrare1.txt.
Dupa rularea programului, obtinem:
9
Definiţia 1. 2. Fie G = (X, U) un graf şi XA .
i) Mulţimea
}.\,),,(/{)( AXxAaxauUuA
se numeşte mulţimea arcelor incidente cu A către exterior.
ii) Mulţimea
}.\,),,(/{)( AXxAaaxuUuA
se numeşte mulţimea arcelor incidente cu A către interior. Mulţimea arcelor incidente cu A este mulţimea:
).()()( AAA
Definiţia 1. 3. Fie G = (X, U) un graf şi ),...,,( 21 quuu un şir de arce.
i) Dacă şirul are proprietatea că extremitatea finală a arcului
iu coincide cu extremitatea iniţială a arcului 1iu , atunci se numeşte drum. Numărul de arce care compun un drum se numeşte lungimea drumului, în cazul nostru lungimea fiind q. Un drum se numeşte elementar dacă nu foloseşte de două ori acelaşi vârf, iar dacă nu foloseşte de două ori acelaşi arc se numeşte simplu. Dacă extremitatea finală a arcului qu coincide cu extremitatea iniţială a arcului 1u , drumul se numeşte circuit.
ii) Dacă şirul are proprietatea că o extremitate a arcului iu coincide cu o extremitate a arcului 1iu , iar cealaltă extremitate a arcului
1iu coincide cu o extremitate a arcului 2iu , atunci se numeşte lanţ. Numărul de arce care compun un lanţ se numeşte lungimea lanţlui, în cazul nostru lungimea fiind q. Un lanţ se numeşte elementar dacă nu foloseşte de două ori acelaşi vârf, iar dacă nu foloseşte de două ori acelaşi arc se numeşte simplu. Dacă o extremitate a arcului qu ,
10
necomună cu arcul 1qu , coincide cu o extremitate a arcului 1u , necomună cu arcul 2u , lanţul se numeşte ciclu. În cazul grafurilor neorientate cele două noţiuni, de lanţ şi drum, coincid. Definiţia 1. 4. Fie G = (X, U) un graf ,XA ,UV o submulţime de vârfuri, respectiv arce. i) Subgraful generat de submulţimea de vârfuri A este un graf,
)},(,{)( AUAAG unde }.,),,(/{)( AyxyxuUuAU ii) Graful parţial al unui graf G, generat de submulţimea de arce V, este graful G’= (X, V), adică graful care are aceleaşi vârfuri ca şi G dar arcele sale sunt din mulţimea V. Definiţia 1. 5. i) Fie G = (X, U) un graf. El este tare conex dacă pentru oricare două vârfuri Xyx , există un drum de la x la y şi un drum de la y la x. O componentă tare conexă a grafului G este un subgraf G(A) al lui G, cu ,XA care este tare conex şi este maximal faţă de această ptoprietate în raport cu incluziunea.(Acest lucru înseamnă că dacă luăm ,\ AXx subgraful lui G, generat de ),(},{ BGxAB nu mai este tare conex). ii) Un graf G este conex dacă pentru orice două vârfuri diferite,
,, Xyx putem găsi un lanţ care să aibă ca extremităţi aceste două vârfuri. O componentă conexă a grafului G este un subgraf G(A) al lui G, cu ,XA care este conex şi este maximal faţă de această ptoprietate în raport cu incluziunea.(Acest lucru înseamnă că dacă luăm ,\ AXx subgraful lui G, generat de ),(},{ BGxAB nu mai este conex). Fie G = (X, U) un graf. Pe mulţimea X definim următoarea relaţie binară: x ~ y dacă şi numai dacă x = y sau există un drum de la x la y şi un drum de la y la x. Această relaţie este o relaţie de echivalenţă, iar clasele de echivalenţă ale acestei relaţii de echivalenţă sunt componentele tare conexe ale grafului G. Dacă pe mulţimea X definim următoarea relaţie binară: x y dacă şi numai dacă x = y sau există un lanţ care are ca extremităţi pe x şi y, atunci această relaţie este o relaţie de echivalenţă, iar clasele de echivalenţă ale acestei relaţii de echivalenţă sunt componentele conexe ale grafului G.
11
Ştim că o relaţie de echivalenţă determină pe mulţimea pe care a fost dată o partiţie, deci componentele conexe si tare conexe ale unui graf definesc o partiţie pe mulţimea de vârfuri X.
Definiţia 1. 6. Fie G = (X, U) un graf, Xx un vârf dat. Definim
)(),...,(}{ )1(2 xk
xxk
xxxx y ,
iar
...}{ˆ 2 xxx x
o submulţime a mulţimii X formată din x şi din toate vârfurile care se găsesc pe drumuri care pleacă din x. Cu aceste notaţii definim aplicaţia:
xxXX ˆ)(ˆ,:ˆ
şi obţinem graful ),ˆ,(ˆ XG numit închiderea tranzitivă a grafului G.
Definiţia 1. 7. Fie G = (X, U) un graf, Xx un vârf dat. Definim
)(),...,(}{ )1(2 xk
xxk
xxxx y ,
iar
...}{ˆ 2 xxx x
o submulţime a mulţimii X formată din x şi din toate vârfurile care se găsesc pe drumuri care se termină în x. Cu aceste notaţii definim aplicaţia:
xxXX ˆ)(ˆ,:ˆ
şi obţinem graful ),ˆ,(ˆ XG numit închiderea tranzitivă inversă a grafului G.
12
Folosind notaţiile de mai sus, pentru orice două vârfuri ,, Xyx definim relaţia binară:
,ˆˆˆˆ yyxy xyşixyx
care este o relaţie de echivalenţă. Atunci, clasa de echivalentă a vârfului y este ,ˆˆ)( yyyC adică tocmai componenta tare conexă a vârfului y. Definiţia 1. 8. Un graf orientat G = (X, U) este complet, dacă orice două vârfuri sunt legate printr-un arc sau două arce în sensuri opuse, adică pentru orice ,, Xyx avem .),(),( UyxUyx Dacă graful nu este orientat, atunci el este complet dacă şi numai dacă orice două vârfuri sunt unite printr-o muchie.
În Figura 1.2. avem graful neorientat complet de ordin 5, K5.
Figura 1.2.
Definiţia 1. 9. Fie G = (X, U) un graf. Fie XA o submulţime de varfuri ale grafului G. A este o clică a grafului G dacă subgraful generat de A, G(A), este complet.
1
2
3
4
5
13
CAPITOLUL 2
DRUMURI OPTIME ÎNTR-UN GRAF
§ 2.1. Matrice asociate unui graf Fie G = (X, U) un 1-graf (sau graf orientat), cu X = {x1, x2 ,…., xn } mulţimea vârfurilor sale. Acestui graf i se asociază o matrice
njijiaA,1,, )(
Mn (R), astfel:
aij =
.,0
,),(,,1
altfelUxxadicăadiacentesuntxşixdacă jiji
Dacă avem o buclă ),( ii xx U, atunci aii = 1, în caz contrar aii = 0. Această matrice se numeşte matricea de adiacenţă asociată grafului G.
Pentru grafuri neorientate matricea de adiacenţă este dată astfel:
aij =
.,0
,,1
altfelxşixîntremuchieexistădacă ji
14
În această situaţie, matricea A este o matrice simetrică cu coeficienţi reali, a cărei urmă este zero. Fiind simetrică si cu coeficienţi reali, ea admite valori proprii reale. Deoarece elementele matricei A corespund, de fapt, unei numerotări arbitrare a vârfurilor, este interesant de găsit proprietăţile care sunt invariante faţă de schimbarea liniilor si coloanelor în funcţie de numerotarea aleasă. Program 3. Determinarea matricei de adiacenta a unui graf orientat/neorientat in C++. //Matrice de adiacenta #include <stdio.h> #include<iostream.h> int adj[100][100]; int n; main() { int max_muchie,i,j,origin,destin; char graph_type; printf("Introduceti numarul de varfuri : "); scanf("%d",&n); printf("Introduceti tipul de graf, orientat sau neorientat (o/n) : "); fflush(stdin); scanf("%c",&graph_type); if(graph_type=='n') max_muchie=n*(n-1)/2; else max_muchie=n*(n-1); for(i=1;i<=max_muchie;i++) { printf("Introduceti muchia %d( 0 0 pentru a iesi ) : ",i); scanf("%d %d",&origin,&destin); if( (origin==0) && (destin==0) ) break;
15
if( origin > n || destin > n || origin<=0 || destin<=0) { printf("Muchie invalida \n"); i--; } else { adj[origin][destin]=1; if( graph_type=='u') adj[destin][origin]=1; } } printf("Matricea de adiacenta este :\n"); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) printf("%4d",adj[i][j]); printf("\n"); } }
Ca exemplu, dupa rularea acestui program, obtinem:
16
Definiţia 2.1.1. Vom numi spectrul grafului G=(X, U), mulţimea
SpecG = {1 >2 >…>p / PA (i) = 0, i valoare proprie de ordin
de multiplicitate mi }, unde PA( ) este polinomul caracteristic al matricei A.
Putem reprezenta spectrul unui graf sub forma unei matrice S M2,p (R),
SG=
p
p
mmm
...
...
2
2
1
1 .
Exemplul 2.1.2. Pentru graful neorientat complet de ordin cinci, K5 , matricea de adiacenţă este:
A =
01111
10111
11011
11101
11110
, iar 5KS =
3114
.
17
Numim valori proprii pentru graful neorientat G valorile proprii corespunzătoare matricei sale de adiacenţă A iar polinomul caracteristic PA() ataşat matricei de adiacenţă A va fi polinomul caracteristic al grafului neorientat G, notat la fel:
PA() = n - 1n-1 + 2n-2 - 3n-3+…+(-1)nn
,
unde i reprezintă suma minorilor principali ai matricei A, de ordin i. Polinomul caracteristic al matricei de adiacenţă A ne poate da diverse informaţii despre graful studiat, după cum vom vedea în cele ce urmează.
Propoziţia 2.1.3. Fie G=(X, U) graf neorientat , A matricea sa de adiacenţă şi PA() polinomul caracteristic asociat. Atunci:
a) 1 = 0; b) 2 = - |U| =
jiji ;
c) - 3 = 2N, N este numărul triunghiurilor care pot fi formate cu vârfurile grafului G.
` Demonstraţie: a) Ştim că 1 = Tr A = 0.
b) Deoarece i este suma minorilor principali ai matricei A, de ordin i, avem că 2 este suma tuturor minorilor de ordin doi de forma
0110
, care sunt în număr de 2nC . Un astfel de minor, care are valoarea
-1, corespunde fiecărei perechi de vârfuri adiacente din graf. Atunci avem că 2 =- |U|, iar ultima relaţie rezultă folosind relaţiile lui Viète.
c) Minorii principali de ordin trei ai matricei A sunt de forma:
001001110
,000001010
,011101110
,
primul având valoarea 2 iar ultimii doi sunt nuli. Acest minor nenul corespunde unui triunghi pe care-l putem forma cu vârfurile grafului. Deci -3 = 2N.□
18
Propoziţia 2.1.4. Fie G=(X, U) un graf neorientat. Atunci numărul drumurilor de lungime l din G care unesc vârfurile xi cu xj ,
ji xx , este dat de elementul aflat pe poziţia(i,j) din matricea Aq, unde A este matricea de adiacenţă a grafului G.
Demonstraţie: Prin inducţie după q. Pentru l=0, deoarece A0 =I, afirmaţia este adevărată. Pentru q=1, Aq=A, obţinem matricea de adiacenţă, deci afirmaţia este adevărată. Presupunem afirmaţia adevărată pentru q şi o demonstrăm pentru q+1. Avem:
.)(1 1
)1(1
,1,1
)(1hj
n
h
n
kkh
qikij
q
nji
n
kkj
qik
qq aaaAAaaAAA
În cazul nostru, din ipoteza de inducţie,
n
kkh
qik aa
1
)1( reprezintă numărul
tuturor drumurilor de lungime q între xi şi xh. Dacă xh este adiacent cu xj atunci ahj =1, altfel ahj =0 şi pentru h{1,2,…,n} vom obţine toate drumurile de lungime q+1 dintre i şi j.□ Definiţia 2.1.5. i) Numărul muchiilor pe care le are cel mai scurt drum dintre xi şi xj se numeşte distanţa în graful neorientat şi conex G dintre vârfurile xi şi xj. ii) Se numeşte diametru al grafului neorientat şi conex G cea mai mare distanţă dintre oricare două vârfuri ale grafului dat.
Propoziţia 2.1.6. [Biggs] Fie G=(X, U) un graf conex
neorientat cu n vârfuri şi de diametru . Atunci graful G are cel puţin +1 valori proprii distincte.
Demonstraţie. Fie A matricea de adiacenţă a grafului G şi
fie xi, xj X, două vârfuri ale grafului G, astfel încât există ),,(),...,,(),,(
1211 iiiiii xxxxxx
cu i
x = xj , drum de lungime între xi şi
xj . Pentru orice ,1k , vom considera matricea Ak. Deoarece între xi şi
kix avem cel puţin un drum de lungime k, rezultă că în Ak vom avea pe poziţia (i, ik) un element nenul, iar matricele I, A,…, Ak-1 pe aceeaşi
19
poziţie, (i, ik), au zero. Într-adevăr, deoarece drumul dintre xi şi xj este cel mai scurt, de lungime , rezultă că drumul dintre xi şi
kix , de
lungime k, k≤ , este cel mai scurt. Dacă pe poziţia (i, ik) din matricea Ak-1 avem un element nenul, rezultă că între xi şi
kix avem un drum de
lungime k-1, deci înseamnă că putem elimina un vârf din şirul {
kiii xxx ,...,,1
} şi atunci între xi şi xj vom avea un drum de lungime strict mai mică decât , fals.
Din cele de mai sus, rezultă că matricele {I, A,…, A } sunt liniar independente în Mn (R), deci polinomul caracteristic are cel puţin +1 valori distincte. Într-adevăr, dacă am avea t valori proprii distincte, cu t< +1, atunci polinomul minimal al matricei A ar avea gradul t. De aici rezultă că matricele {I, A,…, At} ar fi liniar dependente, fals.□
Propoziţia 2.1.7. a) Fie G un graf neorientat cu n vârfuri .
Atunci graful G este conex dacă şi numai dacă matricea (A+I)n-1 nu are nici un element nenul.
b) Dacă G este un graf neorientat, cu n vârfuri şi cu m muchii, care are valorile proprii 1 ≥2 ≥…≥n, atunci avem:
i) 01
n
ii ;
ii) mn
ii 2
1
2
;
iii) .)1(21 n
nm
Demonstraţie: a) Presupunem că graful G este conex. Rezultă că
între orice două vârfuri avem un drum. Fie X={x1,x2,…,xn} vârfurile grafului. Fie d diametrul grafului. Atunci între orice două vârfuri, xi şi xj, există un drum care are lungimea maxim d 1 n , pe care o notăm lij. Atunci matricea ijlA va avea pe poziţia (i,j) un element nenul. Deci, în matricele A, A2,..., Ad nu există o poziţie (i,j) care să fie nulă în toate aceste d matrice, decât dacă i = j. Atunci în matricele I, A, A2,..., Ad nu există o poziţie (i,j) care să fie nulă în toate, deci (A+I)n-1 nu are nici un element nenul.
20
Reciproc, deoarece (A+I)n-1, are numai elemente nenule, avem că între orice două vârfuri distincte ale grafului G avem un drum. Dacă nu ar fi aşa, pentru orice 1,1 nt , At ar avea pe poziţia (i, j) element nul, fals.
b) Afirmaţia i) este evidentă. ii)Avem că
j
n
jiinn
1
222
21
221 2......0 , de une rezultă că
222
21 ... n = 2m.
iii) Folosim inegalitatea Cauchy-Schwarz pentru numerele reale (2 …n) şi (1,1,…,1).
Rezultă
.12
1211121
21
21
21
21
2
2
2
nnm
nmnnmnn
i
ni
n
ii
Demonstraţia este astfel încheiată. □
§ 2.2. Determinarea matricei drumurilor într-un graf. Determinarea componentelor tare conexe
În cele ce urmează, ne vom ocupa de grafuri orientate sau de 1-grafuri. Fie G=(X,U) un graf şi A matricea sa de adiacenţă.
Definiţia 2.2.1. Matricea drumurilor grafului G, notată A* = njiija ,1,*
, este definită astfel:
21
.,0
,,1*
contrarcazînxînajungeşixdinpleacăcedrumungrafînexistădacă
a jiij
Algoritmul ROY- WARSHALL
Fie G=(X,U) un graf orientat cu X = n. Uneori este interesant de găsit, într-un graf, dacă există un drum între două noduri, mai mult decât a găsi distanţa minimă dintre ele. Acest algoritm determină matricea drumurilor A* pornind de la matricea de adicenţă A.
Descrierea algoritmului.
Pasul 1. Se face k=1.
Pasul 2. Pentru i = n,1 şi j = n,1 , i≠k, j k, se înlocuiesc elementele aij = 0 cu min{aik, akj}.
Pasul 3. Se face k = k+1 şi se repetă Pasul 2, până când k ia valoarea n.
Justificare. La Pasul k al algoritmului se obţine o matrice M(k) care este matricea de adiacenţă a unui graf găsit la Pasul k-1, prin introducerea unui arc între două vârfuri neadiacente, xi şi xj, care erau legate printr-un drum de lungime 2, de la xi la xj şi care trece prin xk . La sfârşit, pentru k = n, se obţine matricea A*. Elementul 1 de pe poziţia (i,j) din matricea A* arată că între xi şi xj există un arc.
Observatia 2.2.2. Matricea M(k+1) obtinuta din matricea A, la pasul k+1, se obţine din matricea M(k) prin adăugarea elementelor 1 de pe linia k pe aceeaşi poziţie pe liniile care au pe coloana k elementul 1.
22
Program 4. Algoritmul implementat in C++ este: //Algoritmul Roy-Warshall-varianta 1 #include<conio.h> #include<stdio.h> int a[100][100],k,n,i,j,dr[100][100]; void roywar(int i, int j) { if (a[i][j]==1) dr[i][j]=1; else {for(k=1;k<=n;k++) for (i=1;i<=n;i++) for (j=1;j<=n;j++) if (dr[i][j]==0) dr[i][j]=(dr[i][k])&&(dr[k][j]); } } void main(void) { printf("dati n:");scanf("%d",&n); for(i=1;i<=n;i++) for(j=1;j<=n;j++) { printf("a[%d][%d]=",i,j);scanf("%d",&a[i][j]); a[i][i]=0; } printf("Matricea de adiacenta a grafului este:nn"); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) printf("%4d",a[i][j]); printf("n"); } printf( " "); printf("Matricea drumurilor este:n"); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) {roywar(i,j); printf("%4d",dr[i][j]);
23
} } printf( " "); for (i=1;i<=n;i++) for (j=1;j<=n;j++) { roywar(i,j); if (dr[i][j]==1) printf("nExista drum intre nodul %d si nodul %dn",i,j); else printf("nNu exista drum intre nodul %d si nodul %dn",i,j); } getch(); } Ca exemplu, vom obtine:
24
Algoritmul Roy-Warshall-varianta 2.
//Algoritmul Roy-Warshall-varianta 2 #include <iostream> #include <iomanip> using namespace std; int main() { bool A[31][31]; int n,m; cout<<"Numarul de noduri: "; cin>>n; cout<<"Numarul de muchii: "; cin>>m; //initializam matricea cu 0 for(int i=0;i<=30;i++) for(int j=0;j<=30;j++) A[i][j]=0; //citim matricea de adiacenta a grafului for(int i=1;i<=m;i++) { cout<<"Arcul "<<i<<" "; int x,y; cin>>x>>y; A[x][y]=1; } //aplicam transformarile pe matrice for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(A[i][j]==0) A[i][j]=A[i][k]*A[k][j]; cout<<"Matricea drumurilor este:"<<endl; for(int i=1;i<=n;i++) {
25
for(int j=1;j<=n;j++) cout<<std::fixed<<std::setw(3)<<std::left<<A[i][j]; cout<<endl; } return 0; } Folosind exemplul de mai sus, obtinem rezultatul asteptat:
Algoritmul Roy- Warshall ne dă şi o metodă de determinare a componentelor tare conexe într-un graf.
O componentă tare conexă a unui graf este un subgraf C al lui G care este tare conex şi care este maximal în raport cu incluziunea faţă de această proprietate. Dacă G = (X, U) este un graf, relaţia binară pe X definită prin : “ x = y sau există un drum de la x la y şi un drum e la y la x “, este o relaţie de echivalenţă. Notăm cu C1, C2, ..., Cp clasele de echivalenţă în raport cu această relaţie de echivalenţă. Acestea sunt de fapt componentele tare conexe ale grafului G. Cum oricărei relaţii de
26
echivalenţă îi corespunde o partiţie, rezultă că, într-un graf, componentele tare conexe definesc o partiţie a mulţimii X . Procedeu de determinare a componentelor tare-conexe
Cu ajutorul matricei drumurilor, determinata de algoritmul Roy-Warshall, se pot determina componentele tare conexe astfel: i) Se alege un vârf ix , se parcurge linia şi coloana i din A*, se determină elementele neneule cât şi poziţiile lor. Elementele de pe linia i corespunzătoare poziţiilor nenule determină mulţimea
ix̂ , iar cele de pe
coloana i determină ix
ˆ , deci C(xi) = ix̂
ixˆ .(vezi definitiile 1.6. si
1.7.) ii) Se suprimă elementele din C(x) şi se continuă procedeul. Program 5. Algoritmul de determinare a componentelor tare conexe implementat in C++ este: //Algoritmul Roy-Warshall-componente-tare-conexe #include "stdio.h" int n, a[20][20], viz[20], d[20][20]; void citire() { FILE * f = fopen("graf.txt","r"); fscanf(f,"%d", &n); int i,j; while(!feof(f)) { fscanf(f,"%d %d", &i, &j); a[i][j]=1; d[i][j]=1; a[i][i]=1; d[i][i]=1; a[j][j]=1; d[j][j]=1; } } /* afisarea componentelor tare conexe */ int conex_tare() { /* Roy Warshall */ int i,j,k; for(k=1; k<=n; k++) for(i=1; i<=n; i++) for(j=1; j<=n; j++) if(d[i][k] && d[k][j])
27
d[i][j]=1; int ok=1; for(i=1; i<=n; i++) for(j=1; j<=n; j++) if(d[i][j]==0) ok=0; return ok; } void df(int vf) { int i; viz[vf]=1; printf("%d ",vf); //afisare for(i=1; i<=n; i++) if((d[vf][i]==1 && d[i][vf]) && viz[i]==0) df(i); } int main() { citire(); if(conex_tare()) printf("este tare conex\n"); else printf("nu este tare conex\n"); int i; df(1); for (i=1; i<=n; i++) if(viz[i]==0) { printf("\n"); df(i); } printf("\n"); return 0; }
Algoritmul lui Malgrange Acest algoritm determină componentele tare conexe ale grafului orientat G , pornind de la matricea sa de adiacenţă A. Pasul 1. Se determină x̂ . Această mulţime va fi reprezentată printr-un vector de lungime n care va avea zero în căsuţa
28
corespunzătoare vârfului x. Căutăm arcele care pleacă din x prin citirea liniei corespunzătoare vârfului x. În poziţiile unde găsim 1, pe aceleaşi poziţii, vom pune 1 în vectorul x̂ . Căutăm în x̂ vârfurile marcate cu 1 şi apoi căutăm pe liniile lor, din matricea A, elementele egele cu 1. Pe aceste poziţii în x̂ vom pune 2. La fel procedăm cu vârfurile marcate cu 2. Pe liniile corespunzătoare lor din A căutăm poziţiile marcate cu 1. În
x̂ , aceste poziţii vor fi marcate cu 3, ş. a. m. d. Vârfurile care nu mai pot fi marcate prin acest procedeu vor primi semnul “- „ în casuţa corespunzătoare lor în x̂ . Pasul 2. Se determină Cx. Această mulţime va fi reprezentată printr-un vector de lungime n. Poziţia corespunzătoare vârfului x va fi marcată cu zero. Punem 1 pentru orice vârf de pe coloana vârfului x care are 1 şi vare se află în x̂ . Pentru vârfurile xi care au fost marcate cu 1 în Cx punem 2 , în Cx, pe poziţiile în care găsim elemente egale cu 1 pe coloanele corespunzătoare lor din matricea A* şi care se află şi în
ix̂ , ş. a. m.d. Găsim astfel Cx . Considerăm xCXx şi continuăm procedeul.
Exemple. 1) Algoritmul Roy-Warshall.
Se da graful care are matricea de adiacenta A data in urmatorul tabel:
29
0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0
Cu algoritmul Roy-Warshall, sa se determine matricea drumurilor si componentele tare-conexe. Rezolvare. Pasul 1. i≠1 si j≠1. Pentru a lucra mai usor, vom folosi Observatia
2.2.2.. Se observa ca in coloana 1, avem un singur element egal cu 1(cel cu rosu din A) si aflat pe pozitia 2. Insemana ca, la acest pas, se va modifica doar linia 2, copiindu-se elementele egale cu 1 din linia 1 in pozitiile corespunzatoare din linia 2, si anume doar elementul aflat pe pozitia (2,3)(cu albastru in A), care va deveni 1. La pasul 1, matricea obtinuta va fi M(1) si va avea expresia:
0 0 1 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0
Pasul 2. i≠2 si j≠2 Se observa ca in coloana 2, in M(1), avem 2
elemente egale cu 1(cele cu rosu din M(1)) si se afla pe pozitiile 3 si 4.
A=
M(1)=
30
Insemana ca, la acest pas, se vor modifica liniile 3 si 4, copiindu-se elementele egale cu 1 din linia 2, in aceleasi pozitii, in liniile 3 si 4, adica in pozitiile cu albastru din M(1). Matricea M(2) va fi
0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0
Pasul 3. i≠3 si j≠3 Se observa ca in coloana 3, in M(2), avem 5
elemente egale cu 1(cele cu rosu din M(2)) si se afla pe pozitiile 1, 2, 3, 4 si 5. Insemana ca, la acest pas, se vor modifica liniile 1, 2, 3, 4 si 5, copiindu-se elementele egale cu 1 din linia 3, in aceleasi pozitii, in liniile 1, 2, 3, 4 si 5, adica in pozitiile cu albastru din M(2). Matricea M(3) va fi
1 1 1 0 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0
La final, vom avea matricea drumurilor
M(2)=
M(3)=
31
1 1 1 0 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Pentru a determina componentele tare-conexe, alegem varful x1. Parcurgem linia 1 si gasim
1ˆ
x ={1,2,3}. Parcurgem coloana 1 in A* si
gasim 1
ˆx ={1,2,3,4,5,6,7}. Atunci C(x1) = 1
ˆx 1
ˆx ={1,2,3}={x1, x2,
x3}= componenta tare-conexa a varfului x1. Componenta tare conexa a varfului x4 va fi C(x2)={1,2,3,4,5,6,7} {4,5,6,7}={4,5,6,7}. Deci C(x4) = {x4, x5, x6, x7}.
Acest lucru se poate verifica si folosind Programul 5. Datele au fost date intr-un fisier graf.txt in care, pe prima linie avem dat un numar natural n ce reprezintă numărul de noduri din G, iar pe următoarele linii se vor afla câte două numere naturale x şi y, separate prin spaţiu, reprezentând muchia orientată (x, y).
In urma rularii programului, vom obtine rezultatul asteptat:
A*=
32
2) Algoritmul Malgrange. Pentru acelasi graf de mai sus, vom aplica
algoritmul malgrange de determinare a componentelor tare conexe. Pentru varful x1, se determina
1ˆ
x . Acesta va fi urmatorul vector: 1 2 3 4 5 6 7 0 2 1 - - - - Acest vector a fost obtinut astfel: varful x1 primeste eticheta 0. Acest varf find etichetat, vom cauta pe linia 1 pozitiile unde avem elemente egale cu 1. Avem o singura pozitie si anume 3. Varful x3 va primi eticheta 1. Mergem pe linia 3 si vom cauta pozitiile unde avem elemente egale cu 1. Avem o singura pozitie si anume 2. Varful x2 va primi eticheta 2. Mergem pe linia 2 si vom cauta pozitiile unde avem elemente egale cu 1. Avem o singura pozitie si anume 1, varf care a mai fost etichetat deja, deci oprim procesul de etichetare. Determinam C(x1). Aceasta va fi in urmatorul vector:
33
1 0 2 1 3 2 4 - 5 - 6 - 7 -
Vectorul a fost obtinut astfel: varful x1 primeste eticheta 0. Acest varf find etichetat, vom cauta pe coloana 1 pozitiile unde avem elemente egale cu 1. Avem o singura pozitie si anume 2. Varful x2, fiind etichetat si in
1ˆ
x va primi eticheta 1. Mergem pe coloana 2 si vom cauta pozitiile unde avem elemente egale cu 1. Avem 3 pozitii si anume {3,4,7}. Varful x3, fiind etichetat si in
1ˆ
x . va primi eticheta 2. Varfurile
x3 si x4 nu sunt etchetate in 1
ˆx , deci nu vor primi etichete. Mergem pe
coloana 3 si vom cauta pozitiile unde avem elemente egale cu 1. Avem {1,4,5}. Varful x1 a mai fost etichetat o data, iat x4 si x5 nu sunt etichetate in
1ˆ
x , deci oprim procesul de etichetare si obtinem C(x1) = {x1, x2, x3}.
3) Pentru varful x4, avem 4ˆ
x 1 2 3 4 5 6 7 2 1 1 0 2 1 1 C(x4) va fi
1 2 3 4 0 5 1 6 2 7 3
34
Deci, C(x4) = {x4, x5, x6, x7}.
§ 2.3. Drumuri optime într-un graf
Fie UXG , un graf orientat cu n varfuri. Fie Ul : R+, o
funcţie ulu numită lungimea arcului u. Lungimea unui drum este
egală cu suma lungimilor arcelor sale, iar distanţa minimă dintre două
vârfuri este cea mai mică lungime a drumurilor dintre două vârfuri. Vom
defini matricele:
njiijdD
,1, ,
ji
jiji
ij
xx
Uxxdacaxxl
d,0
D se numeşte matricea distanţelor directe ale grafului G, şi matricea
distanţelor minime M = njiijm
,1, .
altfel
existăacesteadacăxlaxladedrumuriloralungimemicămaicea
mji
ij ,0
,
35
Algoritmul Roy- Floyd – găseşte matricea distanţelor
minime M pornind de la matricea distanţelor directe D, cât şi drumul
minim.
Descrierea algoritmului:
Pasul 1: 1k
Pasul 2: pentru kjkijinjni ,,,,1,,1
elementul aij se înlocuieşte cu min (aij , aik + akj)
Pasul 3: k → k+1 şi se repetă pasul 2. La sfârşit obţinem
matricea M.
Justificare. Prin inducţie după k.
Fixăm două vârfuri v şi w între care vrem să calculăm drumul de
lungime minimă. Un k-drum între v şi w este un drum care să treacă prin
cel mult k-noduri intermediare.
Vom nota cu P(k) afirmaţia: la pasul k, aij = dmin (u,v) obţinut la
pasul 2 al algoritmului este distanţa minimă a celui mai scurt k-drum
elementar dintre u şi w (dacă există !), altfel este infinit (dacă nu există
un astfel de drum).
Presupunem P(k) adevărată şi să vedem ce se întâmplă cu
dmin (v,w) la pasul k+1. Presupunem că µ este un k+1 – drum de la v la
w. Sunt două posibilităţi, funcţie dacă µ conţine sau nu vârful uk+1 de la
pasul k+1.
36
i) dacă µ este un k-drum, atunci µ nu trece prin nodul uk+1
şi, din ipoteza de inducţie, dmin (v,w) rămâne egală cu
lungimea drumului µ după iteraţia k. Este clar că
dmin (v,w) nu poate fi schimbată la pasul k+1, deoarece
nu avem k+1 drumuri.
ii) Dacă µ este un k+1 – drum, presupunem că µ trece
doar o dată prin vârful uk+1 (pentru că un circuit ar face
să crească distanţa). Atunci µ este suma a două k-
drumuri, µ1 şi µ2, µ1 de la v la uk+1 şi µ2 de la uk+1 la w.
Din ipoteza de inducţie, avem că dmin (v, uk+1) şi dmin
(uk+1,w) sunt lungimile drumurilor µ1 şi µ2 la pasul k.
Se observă că aceste distanţe nu se vor modifica la pasul
k+1, deci lungimea drumului µ la pasul k+1 este suma celor două
drumuri µ1 şi µ2 şi este cea mai scurtă.
Pentru k = n - 1, avem că dmin (v,w) este cea mai mică
distanţă a unui (n-1) – drum de la v la w. Dar deoarece orice
drum este un (n-1) – drum, în cazul nostru, am demonstrat că aij
= dmin (v,w) este distanţa minimă dintre v şi w.
Cu acest algoritm, putem obţine şi drumurile minime
dintre vârfurile grafului. Definim o nouă matrice Δ = (δij)i,j=1,n
ale cărei elemente δij P(X) (deci δij sunt mulţimi de noduri).
Vrem să găsim drumul minim dintre v = xi şi w = xj.
δij va reprezenta mulţimea vârfurilor vecine vârfului w
care se găsesc pe drumuri minime de la v la w.
Iniţial, δij = {xi} dacă aij < şi δij = dacă aij = .
37
Pasul 1. Se face k = 1.
Pasul 2.
- dacă aij < aik + akj , atunci δij = δij;
- dacă aij = aik + akj , atunci δij = δij δkj;
- dacă aij > aik + akj , atunci δij = δkj,
pentru i j, i k, j k.
Pasul 3. Se repetă pasul 2 pentru k = 2,….,n.
La sfârşitul aplicării algoritmului, δij va reprezenta mulţimea
vârfurilor vecine cu w ce se găsesc pe drumurile minime de la v la w.
Program 6. Algoritmul implementat in C++ este:
//Algoritmul Roy-Floyd #include<stdio.h>
#include<conio.h> int pinf= 10000; //pentru plus infinit, o valoare mare care nu exista int a[20][20],n,m; void citire_cost() { FILE *f; int i,j,x,y,c; f= fopen("roy_in.txt","r"); if(f) printf("deschiderea a reusit"); else printf("eroare la deschidere!"); printf("\n"); fscanf(f,"%d",&n); fscanf(f,"%d\n",&m); //initializare matrice for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(i==j) a[i][j]=0; else
38
a[i][j]=pinf; for(i=1;i<=m;i++) {fscanf(f,"%d %d %d\n",&x,&y,&c); a[x][y]=c;} fclose(f); } void afisare_mat() {for( int i=1;i<=n;i++) {for(int j=1;j<=n;j++) if(a[i][j]==pinf) printf(" - "); else printf("%4d ",a[i][j]); printf("\n"); } } void RoyFloyd() // roy floyd {for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(a[i][j]>a[i][k]+a[k][j]) { a[i][j]=a[i][k]+a[k][j]; } } void descompun_drum(int i,int j) //realizeaza descompunerea portiunii de la //i la j prin k {int ok=0,k=1; while(k<=n&&!ok) { if(i!=k&&j!=k) if(a[i][j]==a[i][k]+a[k][j]) { descompun_drum(i,k); descompun_drum(k,j); ok=1;} //g marcheaza daca se poate realiza //descompunerea k++; }
39
if(!ok) { printf(" %d ",j); }//cand “drumul” nu mai poate fi descompus afisez //extremitatea finala } void scriu_drum(int nod_initial,int nod_final) // functia primeste ca parametri //cele doua noduri pt care se determina optimul {if(a[nod_initial][nod_final]<pinf) { printf("lantul de la %d la %d are lungimea %d",nod_initial,nod_final,a[nod_initial][nod_final]); printf("\n un drum optim este: %d ",nod_initial); descompun_drum(nod_initial,nod_final); // apeleaza functia care //afiseaza efectiv lantul } else printf("nu exista lant de la %d la %d ",nod_initial,nod_final); } int main() { int x,y; citire_cost(); printf("\nmatricea ponderilor \n"); afisare_mat(); RoyFloyd(); printf("\n matricea drumurilor optime \n"); afisare_mat(); printf("\n Se determina drumul minim intre varfurile x si y \n"); printf("x="); scanf("%d",&x); printf("y="); scanf("%d",&y); scriu_drum(x,y); _getch(); }
40
Exemplu.
Consideram un graf cu urmatoarea matrice a distantelor directe:
0 1 4 ∞ ∞ ∞
∞ 0 2 5 8 ∞
∞ ∞ 0 2 5 ∞
∞ ∞ ∞ 0 3 5
∞ ∞ ∞ ∞ 0 1
∞ ∞ ∞ ∞ ∞ 0
Matricea Δ, atasata matricei D, va fi
x1 x1 x1 ɸ ɸ ɸ ɸ x2 x2 x2 x2 ɸ ɸ ɸ x3 x3 x3 ɸ ɸ ɸ ɸ x4 x4 x4 ɸ ɸ ɸ ɸ x5 x5 ɸ ɸ ɸ ɸ ɸ x6
Pasul 1. i≠1, j≠1, i≠j. Conform algoritmului, aij se înlocuieşte
cu min (aij , ai1 + a1j). Cum ai1 este infinit, avem ca, la pasul 1, cele doua
matrice raman neschimbate.
D=
Δ=
41
Pasul 2. i≠2, j≠2, i≠j. Conform algoritmului, aij se înlocuieşte
cu min (aij , ai2 + a2j). De exemplu, a13 = min(a13, a12+a23) = min(4,
1+2) = 3. Cum a13> a12+a23, avem ca δ13 = δ23={x2}, etc. Vom obtine:
0 1 3 6 9 ∞
∞ 0 2 5 8 ∞
∞ ∞ 0 2 5 ∞
∞ ∞ ∞ 0 3 5
∞ ∞ ∞ ∞ 0 1
∞ ∞ ∞ ∞ ∞ 0
Matricea Δ, atasata matricei D, va fi
x1 x1 x2 x2 x2 ɸ ɸ x2 x2 x2 x2 ɸ ɸ ɸ x3 x3 x3 ɸ ɸ ɸ ɸ x4 x4 x4 ɸ ɸ ɸ ɸ x5 x5 ɸ ɸ ɸ ɸ ɸ x6
La ultimul pas, vom obtine:
D2=
Δ2=
42
0 1 3 5 8 9
∞ 0 2 4 7 8
∞ ∞ 0 2 5 6
∞ ∞ ∞ 0 3 4
∞ ∞ ∞ ∞ 0 1
∞ ∞ ∞ ∞ ∞ 0
Matricea Δ, atasata matricei D, va fi
x1 x1 x2 x3 x3, x4 x5 ɸ x2 x2 x3 x3, x4 ɸ ɸ ɸ x3 x3 x3, x4 ɸ ɸ ɸ ɸ x4 x4 x5 ɸ ɸ ɸ ɸ x5 x5 ɸ ɸ ɸ ɸ ɸ x6
Se observa ca distanta minima dintre varful x1 si varful x6 este 9. Cum obtinem drumurile minime? Cu ajutorul matricei Δ5, construim urmatoarea structura arborescenta:
D5=
Δ5=
43
Deci, drumurile minime intre varful x1 si varful x6 sunt: µ1 ={x1, x3, x5, x6} si µ2= {x1, x2, x3, x4, x5, x6}, ambele de lungime 9. Observatie. Drumurile minime nu sunt intotdeauna si solutii optime pentru problema data. De exemplu, daca graful dat reprezinta o retea de drumuri, varfurile fiind localitati iar lungimea arcelor fiind distanta dintre ele, si avem o firma de transport care face curse regulate intre x1 si x6, atunci vom alege ca traseu drumul µ2 pentru ca trece prin mai multe localitati. Daca impunem anumite restrictii, de exemplu ocolirea localitatii x4, atunci vom alege drumul µ1.
Acest lucru se poate verifica si folosind Programul 6. Datele au fost date intr-un fisier roy.txt in care, pe prima linie avem date numarul de varfuri si de muchiid din G, iar pe următoarele linii se vor afla câte trei numere care reprezinta nodul initial nodul final si lungimea arcului determinat de cele doua noduri.
44
In urma rularii programului, vom obtine rezultatul asteptat:
Observatie. Algoritmul Roy-Floyd poate calcula si distantele si drumurile maxime pentru grafuri fara circuite, inlocuind in formula “min” cu “max”, iar in maatricea distantelor directe + ∞ cu -∞.
45
Algoritmul Dantzing 1. Determina distantele minime intr-un graf orientat G=(X, U) cu n varfuri si poate detecta si circuitele negative ale grafului, preupunand ca functia distanta poate lua si valori negative, pornind de la matricea distantelor directe, notata doar in acest algoritm cu A=(aij)i,j ϵ{1,...,n}, pentru a evita confuziile.
Fie X = Xn = {x1, x2,...,xn } multimea de varfuri. Acest algoritm determina recursiv distantele minime in subgrafurile generate de multimile de varfuri: X1 = {x1}, X2 = {x1, x2},..., Xn = {x1, x2,...,xn }. Fie multimea de varfuri Xm= {x1, x2,...,xm }, cu m ≤ n si m
ijd distant minima de la xi la xj in subgraful lui G generat de multimea de varfuri Xm, pentru orice i,jϵ{1,...,m}.
Algoritmul. Pasul 1. Definim 21
22112
212 , adad , unde aij este distant directa
de la xi la xj pentru graful G. Daca a12+a21<0, STOP, avem circuitul {x1,x2, x1} de lungime negativa. Daca nu, se trece la pasul 2.
Pasul 2. Daca s-au determinat distantele minime 1mijd , distantele
mijd se calculeaza recurrent astfel:
1) ;11},{min 1
1,1
miadd jm
mijmj
mim
2) ;11},{min 1
1,1
midad m
jimjmj
mmi
Daca exista un índice i astfel incat 11 mi si ,0 m
mimim dd atunci
STOP, deoarece avem un circuit nrgativ in subgraful cu multimea de varfuri Xm, care trece prin varfurile xi si xm. Daca nu, calculam `
3) .,1,1},,{min 1 jimjidddd mmj
mim
mij
mij
La final, obtinem ,nijd distantele minime in graful cu multimea de
varfuri X = Xn = {x1, x2,...,xn }.
46
Pasul 3. Se repeta Pasul 2 pentru mϵ{1,...n}. Exemplu. Sa se aplice acest algoritm pentru graful care are matricea distantelor directe
0 1 2 4 3 0 1 2 ∞ 6 0 1 1 ∞ 5 0
m=2, X2={x1, x2}, .3,1 21
22112
212 adad
m=3, X3 = {x1, x2, x3}, 2}11,2min{},{min 23
21213
211}2,1{
313
adadd
j. Analog,
1}10,23min{323 d ,
9}36,min{},{min 3222131
211}2,1{
331
adadd
j,
,6}6,1min{332 d
1}62,1min{},min{ 332
313
212
312 dddd , .33
21 d m=4, X4 = {x1,x2,x3,x4},
3}12,21,4min{},,{min 3431324
31214
311}3,2,1{
414
adadadd
j,
reprezentand si distant minima dintre x1 si x4. Analog, 1}1,26,49min{,2}11,4,43min{ 4
34424 dd .
1}95,3,1min{},,{min 4333142
32141
311}3,2,1{
441
adadadd
j,
3}5,1,21min{,2}65,0,11min{ 443
442 dd .
1}13,1min{},,min{ 441
414
312
412 dddd ,
,3}12,3min{,1}32,1min{,2}33,2min{ 421
423
413 ddd
3}3,6min{,2}2,9min{ 432
431 dd .
A=
47
Algoritmul Dantzing 2. Determina distantele minime intr-un graf orientat G=(X, U) cu n varfuri. Fie X = {x1, x2,...,xn } multimea de varfuri. Fie t functia distanta minima de la x1 la celelalte varfuri, t(xp)=dmin(x1,xp). Notam cu Xq o submultime cu q varfuri ale grafului G. Pasul 1. Notam X1={x1},si definim t(x1)=0. Pasul 2. Daca s-a determinat multimea Xq={xi1,xi2,…,xiq} , pentru fiecare varf xip din Xq se determina varful yip care nu se gaseste in Xq si este cel mai apropiat de xip, adica lungimea arcului (xip,yip) este minima in multimea lungimilor arcelor care pleaca din xip catre varfuri care nu se afla in Xq, daca aceasta multime de arce este nevida. Daca exista mai multe varfuri, se alege un yip la intamplare. Se determina acel varf yis care verifica egalitatea: t(xis)+l(xis,yis)=
},...,2,1{min
qj{t(xij)+l(xij,yij)} si definim Xq+1=Xq {yis},
definindu-se functia in yis prin t(yis)= t(xis)+l(xis,yis). Daca functia t nu poate fi definita intr-un varf w, rezulta ca nu exista nici un drum de la x1 la w. Exemplu. Vom folosi acelasi graf ca la algoritmul Dantzing 1. Pasul 1. X1={x1}, t(x1)=0. Cel mai apropiat varf de x1este unic determinat si este x2, deci X2={x1,x2}, t(x2)=t(x1)+l(x1,x2)=0+1=1. Pasul 2. Cele mai apropiate varfuri de x1 si x2 , care nu apartin multimii X2, sunt y1=x3 si y2=x3, obtinute astfel: min{t(x1)+l(x1,x3), t(x2)+l(x2,x3), t(x1)+l(x1,x4),t(x2)+l(x2,x4)}= =min{0+2,1+1,0+4,1+2}=2, atins pentru x3. Deci, vom avea X3={x1, x2, x3}. Pasul 3. X3={x1, x2, x3} si y1=y2=y3=x4. Avem t(x1)+l(x1,x4)=4, t(x2)+l(x2,x4)=1+2=3, t(x3)+l(x3,x4)=2+1=3. Minimul este 3, deci t(x4)=3. Algoritmul lui Yen. Fie G=(X, U) un graf orientat cu n varfuri. Fie X = {x1, x2,...,xn } multimea de varfuri. Pornind de la matricea
48
distantelor directe D, algoritmul determina distantele minime de la varful x1 la celelalte varfuri x2, x3,...,xn. Pasul 1. In matricea distantelor directe D, se determina, pe linia 1, minimul distantelor directe d12,d13,…,d1n. Daca acesta se atinge pentru i0, care poate sa nu fie unic, atunci distant minima este sansforma astfel:
.}min{},...,1{11
*1 0
niioii ddd
Pasul 2. Toate elementele din prima linie a matricei D, cu exceptia elementelor d11=0 si
01id , se transforma astfel ).,(min00
011},1{1 iiiiiii dddd
Din matricea astfel obtinuta, se elimina linia si coloana i0, pastrandu-se rangurile initiale pentru liniile si coloanele ramase. Daca matricea obtinuta are rangul 2, atunci elementul d12 din aceasta matrice reprezinta reprezinta distant minima de la x1 la xk, unde k este rangul coloanei a doua din aceasta ultima matrice. Cu ajutorul acestui algoritm, putem determina si drumurile de lungime minima. Daca (xk , xj) este ultimul arc al unui drum minim de la xi la xj, atunci kjikij ddd ** .(*) Se cauta in matricea D, pe coloana varfului xj toate varfurile care sunt adiacente cu xj si care verifica relatia (*). Aceste varfuri se vor gasi inaintea varfului xj intr-un drum minim de la xi la xj. Se repeta procedeul pentru aceste varfuri.
Exemplu. Consideram un graf cu urmatoarea matrice a distantelor
directe:
1 2 3 4 5 6
0 1 4 ∞ ∞ ∞ 1
∞ 0 2 5 8 ∞ 2
∞ ∞ 0 2 5 ∞ 3
∞ ∞ ∞ 0 3 5 4
∞ ∞ ∞ ∞ 0 1 5
∞ ∞ ∞ ∞ ∞ 0 6
D=
49
Vom aplica algoritmul Yen. Pasul 1. Minimul pe prima linie este d12=1, deci va fi distant minima dintre varful x1 si varful x2, .1*
12 d Celelalte elemente de pe linia 1, cu exceptia d11=0 si d12, se transforma astfel: d13=min(d13, d12+d23)=min(4,1+2)=3; d14=min(d14, d12+d24)=min( ,1+5)=6; d15=min(d15, d12+d25)=min( ,1+8)=9; d16=min(d16, d12+d26)=min( ,1+ )= . Eliminam linia si coloana 2. Obtinem urmatoarea matrice care pastreaza vechile ranguri ale liniilor si coloanelor matricei distantelor directe pentru graful initial:
1 3 4 5 6
0 3 6 9 ∞ 1
∞ 0 2 5 ∞ 3
∞ ∞ 0 3 5 4
∞ ∞ ∞ 0 1 5
∞ ∞ ∞ ∞ 0 6
Pasul 2. Minimul de pe prima linie a matricei D1 este 3 si se atinge pentru pozitia 3, deci 3*
13 d . Celelalte elemente de pe linia 1 se transforma astfel: d14=min(d14, d13+d34)=min(6,3+2)=5; d15=min(d15, d13+d35)=min(9,3+5)=8. d16=min(d16, d13+d36)=min( ,3+ )= . Eliminam linia si coloana 3. Obtinem urmatoarea matrice care pastreaza vechile ranguri ale liniilor si coloanelor matricei distantelor directe pentru graful initial:
D1=
50
1 4 5 6
0 5 8 ∞ 1
∞ 0 3 5 4
∞ ∞ 0 1 5
∞ ∞ ∞ 0 6
Pasul 3. Minimul de pe prima linie a matricei D2 este 5 si se atinge pentru pozitia 4, deci 3*
14 d . Celelalte elemente de pe linia 1 se transforma astfel: d15=min(d15, d14+d45)=min(8, 5+3)=8. d16=min(d16, d14+d46)=min( ,5+5)=10. Eliminam linia si coloana 4. Obtinem urmatoarea matrice care pastreaza vechile ranguri ale liniilor si coloanelor matricei distantelor directe pentru graful initial:
1 5 6
0 8 10 1
∞ 0 1 5
∞ ∞ 0 6
Pasul 4. Minimul de pe prima linie a matricei D3 este 8 si se atinge pentru pozitia 5, deci 8*
15 d . Celelalte elemente de pe linia 1 se transforma astfel: d16=min(d16, d15+d56)=min(10,8+1)=9. Eliminam linia si coloana 5. Obtinem urmatoarea matrice care pastreaza vechile ranguri ale liniilor si coloanelor matricei distantelor directe pentru graful initial:
D2=
D3=
51
1 6
0 9 1
∞ 0 6
Matricea are ordinal 2, deci elementul de pe pozitia (1,2) este distant minima dintre x1 si x6, 9*
16 d . Pentru a calcula drumurile minime de la x1 la x6, cautam pe
coloana 6 din matricea D, valorile finite si nenule(= varfurile adiacente cu x6). In cazul nostrum, avem {x4, x5}. Verificam formula
kjikij ddd ** , pentru k=4, k=5, i=1, j=6. Avem 46*14
*16 ddd ? Adica
9=3+5? Nu, deci x4 nu este vecin cu x6 pe un drum minim de la x1 la x6. Se poate afla pe un astfel de drum, dar nu ca vecin al lui x6! Verificam pentru k=5, 56
*15
*16 ddd , deci 9=8+1. Da! Deci, x5 este
vecin cu x6 pe un drum minim de la x1 la x6. Continuam procedeul pentru varful x5, gasind varfurile cu care este vecin, pe drumuri minime de la x1 la x6, etc. Vom gasi drumurile : µ1 ={x1, x3, x5, x6} si µ2= {x1, x2, x3, x4, x5, x6}, ambele de lungime 9.
Algoritmul Bellman – Kalaba. (de determinare a drumului minim pornind de la matricea distanţelor directe D). Acest algoritm poate determina si drumurile pe care se ating distantele minime. Fie G = (X,U) un graf căruia îi ataşăm matricea D = (dij)i,j={1,..n}, a distanţelor directe. Fie vi valoarea minimă a drumurilor µin (i=1,n) existente de la vârful xi la vârful xn, vi =l( µin) şi vn = 0. Conform principiului optimalităţii al lui Bellman(orice subdrum al unui drum minim este minim intre capetele sale), avem că: (*) k
iv )(min 1ij
kjij
dv
j ϵ{ 0,…,n} , i ϵ{ 0,…n-1}, şi vn = 0,
.0ini dv
D4=
52
Algoritmul ia sfârşit atunci când gǎsim un k astfel încât
nivv ki
ki ,1,1 .
Acest algoritm determina si drumurile de lungime minima. Arcul (xi ,xj) aparţine drumului de valoare minimǎ dacǎ şi numai dacǎ ij
ki
kj dvv .
Procedeul este acelasi ca la algoritmul Yen. Algoritmul Bellman-Kalaba pentru determinarea drumului de valoare maximǎ intr-un graf fara circuite Fie ),( UXG un graf fara circuite. Definim matricea distantaelor directe matricea
Uxx
ji
Uxxxxl
dnjidD
ji
jiji
ijij
),(,,0
),(),,(
,1,)(
Fie vi valoarea maximă a drumurilor µin (i=1,n) existente de la vârful xi la vârful xn, vi =l( µin) şi vn = 0. Avem ca (**) k
iv )(min 1ij
kjij
dv
j ϵ{ 0,…,n} , i ϵ{ 0,…n-1}, şi vn = 0,
.0ini dv
Dacǎ ,,0,1 nivv k
iki ne oprim, gǎsind drumul de valoare maximǎ.
Pentru determinarea efectivǎ a drumului maxim, vom proceda ca la (B-K) min. Exemplu. Sa se aplice algoritmul B-K min pentru graful care are matricea distantelor directe data mai jos.
53
0 1 2 3 4 5 6 7
0 0 1 3 5 ∞ ∞ ∞ ∞ 1 ∞ 0 2 ∞ ∞ ∞ 13 ∞ 2 ∞ ∞ 0 4 5 11 14 ∞ 3 ∞ ∞ ∞ 0 6 8 ∞ 15 4 ∞ ∞ ∞ ∞ 0 3 ∞ 9 5 ∞ ∞ ∞ ∞ ∞ 0 2 6 6 ∞ ∞ ∞ ∞ ∞ ∞ 0 4 7 ∞ ∞ ∞ ∞ ∞ ∞ ∞ 0
Avem ,7
0ii dv
.20)...,,min()(min 077003
0302
0201
010
0
0
10
dvdvdvdvdvv jjj
,17)(min 10
1
11
jjjdvv .,14)(min 2
0
2
12 etcdvv jjj
Obtinem astfel
coloana 1iv care este diferita de coloana 0
iv , deci algoritmul continua, calculand coloana 2
iv . .17)...,,min()(min 07
1003
1302
1201
110
1
0
20
dvdvdvdvdvv jjj
.,16)(min 11
1
21 etcdvv jjj
Valorile le gasiti in matricea de mai jos.
0 1 2 3 4 5 6 7 0iv 1
iv 2iv 3
iv 0 0 1 3 5 ∞ ∞ ∞ ∞ ∞ 20 17 17 1 ∞ 0 2 ∞ ∞ ∞ 13 ∞ ∞ 17 16 16 2 ∞ ∞ 0 4 5 11 14 ∞ ∞ 14 14 14 3 ∞ ∞ ∞ 0 6 8 ∞ 15 15 14 14 14 4 ∞ ∞ ∞ ∞ 0 3 ∞ 9 9 9 9 9 5 ∞ ∞ ∞ ∞ ∞ 0 2 6 6 6 6 6 6 ∞ ∞ ∞ ∞ ∞ ∞ 0 4 4 4 4 4 7 ∞ ∞ ∞ ∞ ∞ ∞ ∞ 0 0 0 0 0
D=
54
Pentru determinarea drumurilor minime, avem ca arcul (xi ,xj) aparţine drumului de valoare minimǎ dacǎ şi numai dacǎ ij
ki
kj dvv . Cautam
pe coloana 7 varfurile care sunt adiacente cu x7. Avem ca j=7 si }.6,5,4,3{i
Verificam pentru arcul (x6, x7). Avem .,0006736
37 DAdvv
Verificam pentru arcul (x5, x7). Avem .,5505735
37 DAdvv
Verificam pentru arcul (x4, x7). Avem .,9904734
37 DAdvv
Verificam pentru arcul (x3, x7). Avem NUdvv ,151403733
37 .
s.a.m.d.
55
CAPITOLUL 3
PROBLEME HAMILTONIENE SI EULERIENE
1. Probleme Hamiltoniene
Denumirea de graf hamiltonian provine de la numele
matematicianului Hamilton, care în 1859 a propus un joc constând din găsirea unui ciclu elementar care să treacă prin toate vârfurile unui dodecaedru regulat, marcate cu numele unor oraşe din toată lumea.
Un graf orientat G=(X,U) se numeste graf hamiltonian dacă există un circuit elementar care trece prin toate vârfurile grafului. Un astfel de circuit se numeşte circuit hamiltonian. În cazul grafurilor neorietate, un ciclu elementar care trece prin toate vârfurile grafului se numeşte ciclu hamiltonian, un graf posedând un astfel de de ciclu numindu-se hamiltonian.
Dacă graful orientat G are n vârfuri, un drum hamiltonian al lui G este un drum elementar de lungime n-1, adică un drum elementar care trece prin toate vârfurilre grafului.
În cazul grafului neorientat G un lanţ hamiltonian se defineşte în mod analog, ca un lanţ elementar care trece prin toate vârfurile grafului.
Problemele hamiltoniene îşi găsesc aplicaţii la optimizarea unor procese concrete de distribuire sau colectare, la determinarea succesiunii optime de prelucrare a unor piese pe o maşină, etc.
Exemplul 3.1. Voiaj închis în jurul lumii. Vom lua pe globul
pământesc 20 de oraşe tcba ,,,, ; presupunem că aceste oraşe sunt vârfurile unui docaedru regulat ( poliedru cu 12 feţe pentagonale şi cu 20 de vârfuri) reprezentând Pământul. Vom propune trecerea o singură dată şi numai o singură dată, prin fiecare dintre aceste oraşe şi revenim la punctul de plecare folosind numai muchiile dodecaedrului. Această problemă revine la determinarea unui circuit hamiltonian pentru graful simetric din Figura 3.1.
56
Figura 3.1.
Metoda folosită de Hamilton este următoarea: călătorul ajungând
la extremitatea unei muchii are de ales între muchia care o ia spre dreapta, operaţie pe care o notăm cu D, sau muchia care o ia spre stânga, operaţiei pe care o vom nota cu S1, sau să rămână pe loc, operaţie pe care o vom nota cu 1. Se defineşte apoi un produs între aceste operaţii; DS1 este operaţia care constă în a merge întîi pe muchia din dreapta apoi pe cea din stânga; SSD sau S2D este operaţia care constă în a merge de două ori la stânga şi apoi o dată la dreaptă etc. Două operaţii vor fi egale dacă plecând din acelaşi punct de sosire. Produsul nu este comutativ (adică DS SD) însă este asociativă (adică SSD =S(SD)).
Avem formulele: D5=S5=1
DS2D=SDS SD2S=DSD DS3D=S2 SD2S=D2
Se poate scrie: 1=D5=D2D3=(SD3S)D3=(SD3)2=[S(SD3S)D]2=... ...=(S2D3SD)2=[S2(SD3S)DSD]2=[S3D3SDSD]=...
...=SSSDDDSDSDSSSDDDSDSD. Această secvenţă comportă 20 de litere şi nu se poate izola nici o
secvenţă parţială care să fie egală cu 1; ea reprezintă deci un circuit hamiltonian. Un alt circuit se obţine citind secvenţa în sens invers şi un raţionament simplu ne arată că nu sunt alte circuite hamiltoniene.
57
Voiajul poate să înceapă din diferite puncte ale circuitului circular indicat. Hamilton şi-a fixat dinainte 5 oraşe prin care să treacă, de exemplu edcba ,,,, nu a reţinut decât voiajurile care înceapeau cu muchia ba, şi simbolurile DSD şi a obţinut 4 soluţii:
DSDSDSSSDDDSDSDSSSDD DSDSSSDDDSDSDSSSDDDS DSDSDDDSSSDSDSDDDSSS DSDDDSSSDSDSDDDSSSDS.
Exemplul 3.2. Voiaj deschis în jurul lumii. Dacă în problema precedentă nu se ma i cere să se revină la punctul de plecare, numărul voiajurilor este mult mai mare. Trebuie să se determine toate drumurile hamiltoniene ale grafului din Figura 5.1.
Vom indica toate vârfurile care indică numai drumurile hamiltoniene care încep cu D, deoarece celelalte se pot obţine din aceste schimbând literele D şi S între ele:
DDDSDSDSSSDDDSDSDS DSDSSSDDDSDSDSSSDD DSDDDSSSDSDDDSSSDS DSSSDDDSDSDSSSDDDS DSDSSDDDSDSSSDDSDS DDDSSSDSDSDDDSSSDS DSDDDSSSDSDSDDDSSS DSDSDDDSSSDSDSDDDS DDDSDDSDSDSDSSDSSS DDSDSDSSSDDDSDSDSS DDDSSDSDDDSSSDSDSD DSDSDSSSDDDSDSDSSS DDDSDDSDSDSSSDDDSD DSSSDSDSDDDSSSDSDS DDSSSDSDSDDDSSSDSD DSDSDSSSDDDSDSSDDD DSSSDSDSSDDSDSDDDS DDDSSSDSDSDSDDSDDD DSDDDSSSDSDSDDSDDD DDDSDDSDSDSDSSSDDD DSDSSSDDSDSSDDDSDS DSDSDDDSSSDDSDSSSD DSSSDSDDSSSDDDSDSD DDDSSSDSDSDSDDDSSS DSSSDSDSSDDDSDSSSD DSSSDSDDDSSDSDSSSD DSSSDSDDDSSSDSDDDS (secvenţele grupate corespund la operaţii egale).
58
Exemplul 3.3. Cursa calului pe tabla de şah. (Euler) Vom propune să deplasăm un cal pe tablă de şah astfel ca în drumul său să trecă o singură dată pe fiecare pătrăţel. Acestă problemă, care revine la determinarea unui drum hamiltonian al unui graf simetric, a interesat mai mulţi matematicieni, mai ales pe Euler, de Moivre, Vandermonde etc. Nu vom putea să dăm toate soluţiile şi metodele folosite pentru rezolvare sunt numeroase. O regulă care pare să fie verificată de practică, dar care nu este justificată de teorie, este următoarea: vom plasa de fiecare dată calul acolo unde el domină cel mai mic număr de pătrăţele încă neutilizate.
O altă metodă constă în a căuta un drum închis pe o jumătate de tablă, să-l dublăm prin simetrie să-l racordăm. Această regulă este legată de specificul tabelei de şah şi nu poate fi extinsă la un graf mai general.
În cercetarea operaţională, determinarea unui drum hamiltonian este cheia a numeroase probleme de ordonanţare. Când se caută un ordin optim pentru efectuarea unui anumit număr de acţiuni, care se reprezintă prin punctele nxxx ,,, 21 , se duc arcele ji xx , , când nu se pierde nimic dacă ix se efectuează înainte de jx şi atunci ordonanţarea căutată este, în general, indicată prin unul dintre drumurile hamiltoniene ale grafului.
Exemplul 3.4. Problema cărţilor (S. Johnson). Un tipograf
dispune pentru realizarea a n cărţi de două maşini, una pentru imprimat, alta pentu legat. Fie ka timpul necesar pentru imprimarea celei de a k -a cărţi şi kb timpul pentru legat. Se înţelege, că o carte trebuie împrimată înainte de a fi legată şi, prin urmare, maşina de legat poate sta mai mult sau mai puţin timp. În ce fel trebuie să se lucreze pentru terminarea lucrului cât mai repede posibil?
Se vede imediat că nimic nu se schimbă dacă presupune că în fiecare maşină cărţile intră în aceeaşi ordine. O ordine optimă va fi atunci definită de o permutare niii ,,, 21 sau de scvenţă de operaţii
niii xxx ,,,21 . Pe de altă parte, se poate arăta că într-o anumită ordine
optimă, cartea )(i va fi plasată înaintea cărţii j dacă: ijji baba ,min,min .
59
De fiecare dată când această inegalitate va avea loc, vom duce arcul ji xx , ; pe graful obţinut vom căuta un drum hamiltonian şi dacă el este unic, atunci va indica ordinea optimă căutată.
Teoreme de existenţă Până în prezent nu se cunoaşte o condiţie necesară şi suficientă
de existenţă a ciclurilor (sau lanţurilor, drumurilor, circuitelor) hamiltoniene, valabilă pentru orice graf, de aceea s-au propus numeroase condiţii fie necesare, fie suficiente, pentru existenţa acestor cofiguraţii hamiltoniene.
În continuare vom prezenta teorema lui Chvátal şi corolarele lui Ore şi Dirac relativ la existenţa circuitelor hamiltoniene în 1-grafurile complete şi tare conexe. Demonstratiile lor sunt date in Ioan Tomescu, Combinatorica si Teoria grafurilor.
Teorema 3.5. Dacă G este un graf neorientat cu n vârfuri,
3n , pentru care şirul gradelor vârfurilor sale aranjate în ordine crescătoare nddd ...21 verifică proprietatea
kd k <2n implică knd kn ,
rezultă că graful G este hamiltonian.
Doua consecinţe ale acestei teoreme, au fost găsite anterior de O.Ore şi respectiv G.Dirac:
Corolarul 3.6. Dacă G este un graf simplu cu n vârfuri, 3n , astfel încât pentru orice două vârfuri neadiecente x şi y , să avem:
nydxd )()( , rezultă că G este hamiltonian.
60
Corolarul 3.7. Dacă G este un graf simplu cu n vârfuri, 3n ,
astfel încât pentru orice vârf x gradul său 2
)( nxd , rezultă că G este
hamiltonian. Teorema 3.8. Orice 1-graf complet şi tare conex este
hamiltonian.
Probleme Hamiltoniene în cazul grafurilor orientate Propoziţia 3.9.. Dacă G este un graf orientat şi fără circuite şi
'T este matricea drumurilor sale triangularizată, atunci primul element diferit de zero din fiecare linie a acestei matrici şi ultimul element diferint de zero din fiecare coloană sunt elemente arc. Demonstraţie. Fie 0' ijt primul element de pe linia '
ix . Dacă 'ijt nu este element arc,
atunci există un vârf 'mx pe drumul de la '
ix la 'jx . În matricea 'T ,
0' imt precede pe 'ijt din linia '
ix ceea ce contrazice faptul că 'ijt este
primul element diferit de zero de pe această linie, deci 'ijt reprezintă un
arc. Presepunem că '
ijt este ultimul element diferit de zero de pe coloana j .
Din definiţia matricei triunghiulare, 'ijt este primul element de pe linia i
considerat la punctul precedent. Dacă elementul 'ijt nu este primul
element de pe linie, el poate fi adus pe primul loc într-o linie printr-o schimbare a liniilor şi coloanelor între ele.
61
Propoziţia 3.10. Dacă G este un graf de ordinul N , orientat fără circuite, atunci el conţine un drum hamiltonian, dacă numărul
elementelor diferite de zero din T este egal cu 2
1NN .
Demonstraţie. Un drum hamiltonian este un drum care trece prin fiecare vârf al
grafului, folosind fiecare vârf o singură dată. Dacă graful este de ordinul n , lungimea unui drum hamiltonian, în ipoteza că acesta există, este egală cu 1n .
Vom presupunem că matricea T are 2
1NN elemente diferite
de zero. Matricea T poate fi triangularizată (adică elementele sale de sub şi de pe diagonala principală sunt nule). Fie T matricea conexă terminală triangularizată ale cărui linii corespund în ordine, la vârfurile
''2
'1 ,,, Nxxx , şi ale cărei elemente situate deasupra diagonalei principale
sunt toate diferite de zero. După rezultatul problemei anteriore, fiecare element diferit de zero din 'T este element arc, iar succesiunea de arce corespunzătoare la primul element diferit de zero din fiecare linie este un drum hamiltonian.
Propoziţia 3.11. Un graf orientat şi fără circuite nu poate avea
decât un singur drum hamiltonian.
Demonstraţie. Singura succesiune a vârfurilor ''
2'1 ,,, Nxxx ce conduce la un
drum hamiltonian este de forma ''1
'3
'2
'2
'1 ,,,,,, NN xxxxxx . Orice altă
succesiune a tuturor vârfurilor conţine cel puţin o inversiune a indicilor, căci dacă presupunem că mai există un drum hamiltonian atunci succesiunea de vârfuri corespunzătoare conţine cel puţin un arc de forma '' , ji xx cu ij . De aici, linia '
jx precede linia 'ix în 'T , deci 1' ijt
adică există cel puţin un drum de la 'jx la '
ix ceea ce este incompatibil cu
existenţa în graf a arcului '' , ji xx , cu care ar forma un circuit.
62
Propoziţia 3.12. Pentru graful G de ordinul N , orientat şi fără circuite, se cere să se determine un drum hamiltonian.
Demonstraţie.
Pentru determinarea unui drum hamiltonian în graful G de
ordinul N , orientat şi fără circuite, se cunoaşte următorul algoritm: a) construim matricea terminală T ; b) dacă elementele diagonalei principale din matricea T
sunt toate nule şi numărul elementelor diferite de zero din
T este 2
1NN , G are un drum hamiltonian;
c) aranjăm succesiunea punctelor de atingere ale vârfurilor în ordinea descrescătoare şi obţinem drumul hamiltonian.
Exemplul 3.13. Pentru graful G reprezentat în figura, să se
determine un drum hamiltonian.
Demonstraţie.
Figura 3.2.
63
Vom scrie matrcea de adiacenţă B şi matricea drumurilor directe T corespunzătoare grafului dat:
000100100011110100000001100101000000
B
000101100111110111000001100101000000
T
Deoarece pe diagonala principală din matricea T , toate elementele sunt egale cu zero (deci, graful nu admite circuite) şi numărul
elementelor diferite de zero este 2
)1(15
NN , rezultă că graful dat
admite un drum hamiltonian. Folosind punctul c) din algoritmul prezentat în problema anterioară, găsim după aranjarea vârfurilor grafului în ordinea descrescătoare a puterilor de atingere, următorul drum hamiltonian: 1,3,6,2,5,4Hd .
Exemplul 3.14. Pentru graful G de ordinul n orientat ce
conţine circuite se cere să se determine drumurile hamiltoniane. Rezolvare.
Determinarea drumurilor hamiltoniene într-un graf G, folosind descompunerea grafului în componente tare conexe:
a) determinăm componentele tare conexe ale grafului dat.
b) determinăm matricea conexă a grafului condensat; c) determinăm drumul hamiltonian al grafului condensat,
dacă acesta există; d) păstrând ordinea componentelor tare conexe indicată
de drumul hamiltonian al grafului condensat, determinăm drumurile hamiltoniene din fiecare componentă conexă;
64
e) racordând drumurile găsite cu ajutorul arcelor dintre componentele tare conexe, obţinem drumurile hamiltoniene pentru graful dat.
Exemplul 3.15. Fie graful G reprezentat în Figura 3.3. Folosind descompunerea grafului G în componente tare conexe, să se determine drumurile hamiltoniene existente în graful dat G.
Rezolvare.
Figura 3.3.
Componentele tare conexe ale grafului G sunt date de mulţimile: 6,3,2 , 4,1 , 7,5 , iar matricea conexă a grafului condesat va fi: 2C 1C 5C
000100110
* B 512
CCC
Drumul hamiltonian al grafului condensat este dat de succesiunea vârfurilor: 2C , 1C , 5C ; în fiecare componentă conexă, avem
65
următoarele drumuri hamiltoniene: 2,6,3 , 6,3,2 , 3,2,6 , 4,1 , 1,4 , 5,7 , 7,5 . Racordând drumurile găsite cu ajutorul arcelor dintre componentele tare conexe, găsim drumurile hamiltoniene:
5,7,4,1,2,6,3 , 7,5,4,1,2,6,3
2. Probleme Euleriene
Podurile de la Königsberg
Euler a studiat in 1736 problema podurilor de la Königsberg. Oraşul Königsberg se află aproape de punctul de vărsare a râului Pregolea în Marea Baltică. Râul are pe teritoriul oraşului două braţe confluente iar în punctual de confluenţă se află o insulă, numită “Curtea Hanului”. Această insulă este legată dealuri prin cinci poduri. Peste fiecare braţ al râului mai există câte un pod. Problema care a apărut cerea să se găsească un traseu continuu care să treacă o singură dată pe fiecare din cele şapte poduri.(vezi figura ) Euler a fost primul care a arătat că această problemă nu are soluţie.
Euler a generalizat problema considerand ca ea nu se refera
numai la 4 regiuni terestre, ca la Königsberg, ci la oricate, si ca intre aceste regiuni nu sunt numai 7 poduri, ca la Königsberg, ci un numar oarecare N de poduri, oricum distribuite sau grupate. Cu aceasta ipoteza, a notat fiecare regiune cu cate o litera mare. Pentu Königsberg, a dat
66
insulei numele A, teritoriilor situate de o parte si de alta a insulei le-a spus B si C, iar teritoriul dintre cele doua brate ale raului a fost botezat D.
Dupa aceea, Euler a propus ca traseul cautat, in ipoteza ca exista si ca a fost gasit, sa fie notat astfel: la inceput litera regiunii de plecare, apoi pentru fiecare pod parcurs litera regiunii in care duce podul respectiv si asa mai departe. De exemplu, notatia BACD ar insemna: plecarea din regiunea B, trecerea peste primul pod din regiunea B in A, trecerea peste al doilea pod din A in C, trecerea peste al treilea pod din C in D. Deci notatia traseului va trebui sa cuprinda cate o litera pentru fiecare pod parcurs(dintr-un total de N poduri), plus o litera pentru regiunea de plecare, in total N+1 litere. Se observa ca litera unei regiuni se poate repeta daca acea regiune este legata de alte regiuni prin mai mult decat un singur pod, sau daca traseul incepe si se termina cu aceeasi regiune.
O regiune este caracterizata, in primul rand, prin numarul n de capete de pod aflate pe teritoriul ei, astfel,
a) Regiune impara, daca pe teritoriul ei se afla un numar impar ni de capete de pod. Apar doua posibilitati:
i) Daca traseul porneste din aceasta regiune pe unul din poduri, litera regiunii respectiva apare, in notatia traseului, o data pentru podul de plecare, iar pentru celelalte capete de pod, pentru fiecare pereche(din care pe un pod traseul revine in regiune, iar pe celalalt pleaca din nou din regiune), litera regiunii respective mai apare ica o data. Deci, in total, litera unei regiuni impare, care este in acelasi timp regiune de pornire,
apare, in notatia traseului, de 2
1inori. Se mai observa ca aceasta
regiune de pornire nu poate fi si regiune de incheiere a traseului. ii) Daca traseul nu porneste din aceasta regiune, atunci pentru
fiecare pereche de capete de pod(din care pe unul traseul intra in regiune, iar pe celalalt iese din regiune), litera regiunii respective apare in notatie o data, iar pentru capul de pod ramas stingher, pe care traseul intra in regiune, fara sa mai iasa, litera mai apare o data. Deci, in total de
21in
ori.
b) Regiune para. Daca pe teritoriul regiunii se afla un numar par np de capete de pod. Avem doua cazuri:
67
i) Daca traseul porneste din aceasta regiune pe unul din poduri, litera regiunii respective apare, in notatia traseului, o data pentru podul de plecare si in plus, pentru fiecare pereche dintre celelalte capete de pod, mai apare inca o data, ramanand la urma un capat de pod stingher, pentru revenirea definitiva in regiunea respectiva, ceea ce inseamna ca litera mai apare o data. Deci, in total, litera regiunii pare respective apare
in acest caz, in notatia traseului, de 12pn
ori.
ii) Daca traseul nu porneste din acesta regiune, atunci pentru fiecare pereche de capete de pod(din care pe unul traseul intra in regiune si pe celalalt iese din regiune), litera regiunii respective apare, in notatia
traseului, o data. Deci, in total 2pn
ori.
Concluzii. a) Litera unei regiuni impare cu ni capete de pod
apare in notata traseului de 2
1n ori, fie ca traseul incepe sau se incheie
in acea regiune. b) O regiune impara este sau regiune de inceput sau regiune de
sfarsit al traseului. c) Pentru ca problema sa aiba solutie, trebuie sa avem maximum
doua regiuni impare(una de pornire si una de plecare). d) Daca avem mai mult de doua regiuni impare si numarul este
par, atunci pentru fiecare pereche de regiuni impare va fi necesar un traseu separat, independent.
e) Daca numarul de regiuni impare este impar, problema nu are solutie.
f) Daca avem numai regiuni pare, problema are solutie. In acest caz, una din regiunile pare este in acelasi timp regiune de incepere si de sfsrsit al traseului, iar celelalte regiuni pare sunt regiuni de tranzit. Regiunea initiala si in acelasi timp finala a traseului poate fi oricare din regiunile pare.
Din cele spuse mai sus avem, in cazul de la Königsberg, avem:
68
Regiunea Capete de pod Litera trebuie sa apara de
A 5 3
215
ori
B 3 2
213
ori
C 3 2
213
ori
D 3 2
213
ori
Total 14 9 ori
N= 72
14 poduri.
Litere: N+1=8. Se observa ca, pentru ca problema sa fie posibila, notatia
traseului trebuie sa aiba 8 litere, dar natura regiunilor impune o notatie de 9 litere. Deci, problema podurilor de la Königsberg nu are solutie.
In cazul generalizarii date de Euler, avem: i) Daca avem 2 regiuni impare, una este de incepere,
cealalta de final; ii) Daca avem mai mult de doua regiuni impare si numarul
lor este par, pentru fiecare pereche de regiuni impare este necesar un traseu separat;
iii) Daca avem un numar impar de regiuni impare, problema nu are solutie;
iv) Daca avem numai regiuni pare, problema are solutie si traseul poate incepe din oricare dintre ele.
Definitia 3.16. Se numeste lant(ciclu) Eulerian pentru un graf neorientat, un lant(ciclu) care foloseste o muchie numai o singura data. Facem observatia ca, intr-un graf neorientat, numarul varfurilor de grad impar este par.
69
Propozitia 3.17. Un graf neorientat G=(X,U) admite un lant Eulerian daca si numai daca este conex si numarul varfurilor de grad impar este 0 sau 2. Demonstratie. "" Presupunem ca exista un lant Eulerian. Rezulta ca G este conex. Daca este lant cu varfurile terminale distincte, atunci ele sunt singurele de grad impar.
"" Aratam ca daca exista doua varfuri de grad impar a si b, atunci exista un lant Eulerian care pleaca din a si se termina in b. Daca nu exista puncte de grad impar, atunci exista un ciclu Eulerian. Demonstram dupa numarul de muchii, m. Presupunem afirmatia adevarata pentru grafuri cu numarul de muchii < m si aratam ca este adevrata pentru un graf cu m muchii. Presupunem ca G admite doua varfuri de grad impar, a si b. Un calator ce pleaca din a intr-o directie oarecare si nu parcurge aceeasi muchie de doua ori, va defini un lant µ. Daca va ajunge intr-un varf x≠b, calatorul va utiliza un numar impar de muchii incidente cu x, deci va putea pleca pe o muchie neutilizata. Daca nu va mai putea pleca, atunci va fi in mod necesar in b. Este posibil ca drumul µ sa nu fi folosit toate muchiile. Va ramane un graf partial G’=G-µ care are toate varfurile de grad par. Fie C1, C2,...,Ck componentele conexe in G’ care admit cel putin o muchie. Din ipoteza de inductie, ele admit ciclurile Euleriene µ1,µ2,...,µk. Cum G este conex, lantul µ intalneste succesiv toate aceste componente conexe in varfurile x1ϵC1, x2ϵC2,...,xkϵCk, in aceasta ordine. Considerand lantul µ[a,x1]+µ1+µ[x1,x2]+µ2+...+µ[xk,b], acesta va fi un lant Eulerian de la a la b. □
Algoritmul lui Fleury pentru trasarea unui ciclu Eulerian. Fie G un graf neorientat, conex, cu toate varfurile de grad par. Pentru a determina un ciclu Eulerian, procedam astfel:
1) Se pleaca dintr-un varf oarecare. De fiecare data cand o muchie este parcursa, se anuleaza.
2) Nu se va utiliza o muchie u care in momentul considerat va fi un istm(suprimarea sa produce doua componente conexe avand fiecare cel putin o muchie).
70
Intr-adevar, daca suntem intr-un varf oarecare x≠a, atunci graful are doua varfuri de grad impar x si a, imparitate obtinuta in urma suprimarii unei muchii. Daca se suprima punctele izolate, atunci va ramane un graf conex care admite un lant Eulerian care pleaca din x. De ce putem respecta mereu aceasta regula? Presupunem ca am ajuns in varful x, care acum este impar si sa presupunem ca toate muchiile incidente acum cu x sunt istmuri. Daca am avea doar o muchie in x, atunci aceasta ar fi suspendata, deci celalat capat ar fi un varf impar diferit de a sau x, fals. Deci, avem cel putin doua istmuri, care duc fiecare la cate 2 componente conexe disjuncte, avand fiecare un varf de grad impar. Cum a si x sunt singurele varfuri impare, avem o contradictie. Deci, putem gasi in x o muchie care sa nu fie istm si care sa fie eliminata.
Un circuit Eulerian intr-un graf orientat este un circuit ce
utilizeaza fiecare arc o singura data. Definitia 3.18. Un graf orientat G=(X,U) este pseudo-simetric
daca xx , xϵX, adica numarul arcelor ce intra in varful x este
egal cu numarul arcelor care ies din acel varf. Propozitia 3.19. Un graf admite un circuit Eulerian daca si
numai daca este conex si pseudo-simetric. Propozitia 3.20. Orice graf finit neorientat este Eulerian(admite
un ciclu Eulerian) daca si numai daca: 1) Este conex; 2) Orice varf este de grad par.
Demonstratie. "" Daca avem un graf Eulerian, atunci este
conex. Deoarece daca un drum ajunge intr-un varf, trebuie sa si iasa din el, rezulta ca trece de doua ori prin acelasi varf, deci conditia 2) este satisfacuta.
"" Fie µ un ciclu ce pleaca din a si trece, pe cat este posibil, prin cate o noua muchie. Deoarece pentru fiecare varf numarul muchiilor este par, putem ajunge in a. Daca µ nu trece prin toate muchiile lui G, vom
71
scoate din G muchiile acestui ciclu. Nota cu G1 graful ramas. Cum G si µ au varfuri de grad par si G1 va avea varfurile de grad par. Cum G este conex, exsta bϵX astfel incat µ trece prin b si bϵG1. Cu acelasi procedeu, din b putem construi un ciclu nou µ1 ce contine numai muchii din G1. Atunci avem ca µ1=µ(a,b)+µ1+µ(b,a) este ciclu care contine mai multe muchii din G decat µ. Daca nu este Eulerian, se continua procedeul. □ O alta problema este determinarea numarului minim de lanturi distincte („trasaturi de condei”) din care poate fi facuta o figura(acoperirea ei). Fie G un graf care nu este Eulerian si fie k numarul varfurilor de grad impar. Fiecare varf impar trebuie sa fie varf de plecare sau varf de sosire pentru cel putin unul dintre aceste lanturi
µi. Deci, numarul unor astfel de drumuri este cel putin 2k . Vom arata
ca G poate fi acoperit cu exact 2k lanturi. Pentru aceasta, vom mari
numarul de muchii din G cu 2k muchii, fiecare avand o alta pereche
diferita de varfuri impare. Vom obtine un nou graf G1, iar multimea de muchii adaugata o vom nota U1. In acest fel, in graful G1, fiecare varf, care era impar in G, va deveni par deci, in G1, vom avea un ciclu Eulerian µ1. Cand excludem multimea de muchii U1 din µ1, vom
obtine 2k lanturi care acopera pe G.
Propozitia 3.21. Fie G un graf finit si conex cu k varfuri de ordin impar. Atunci, numarul minim de lanturi distinct care acopera graful G
este 2k .
72
CAPITOLUL 4
REŢELE DE TRANSPORT. ALGORITMUL FORD-FULKERSON
§ 4. 1. Reţele de transport
Fie ),( UXG un graf orientat cu },...,,{ 1 no xxxX . G defineşte o reţea de transport dacă îndeplineşte următoarele condiţii:
i) G este conex şi fără bucle; ii) Există un vârf unic Xxo în care nu intră nici un arc,
deci ox . iii) Există un vârf unic Xxn din care nu pleacă nici un arc,
deci nx .
iv) Pentru orice arc Uxxu ji ),( s-a definit o funcţie pe mulţimea arcelor U cu valori reale şi positive c:UR+.
Numărul c(u) se numeşte capacitatea arcului (u), vârful ox se numeşte intrarea reţelei, vârful nx se numeşte ieşirea reţelei. Reţeaua va fi notată ),,( cUXG . Varfurile retelei se mai numes si noduri.
O funcţie RU: se numeste flux atasat unei retele de transport, ),,( cUXG , dacă sunt îndeplinite condiţiile:
a) Uuu ,0)( ; b) Uuucu ),()( (condiţia de mărginire a fluxului); c) 1,1,)()(
)()(
uiuuii xuxu
(condiţia de conservare a
fluxului in fiecare nod al retelei). Din condiţia de conservare a fluxului obţinem că fluxul care iese
din oox , , este egal cu cel care intră în nnx , .
73
Fie ),,( cUXG o reţea de transport şi XA cu proprietatea că Axo dar Axn .
Mulţimea )( A a arcelor ce au extremitatea finală în A, iar cea iniţială în X-A se numeşte tăietură a reţelei. Capacitatea tăieturii este suma capacităţilor arcelor din tăietură:
.)()()(
Au
ucAc
Observaţia 4.1.1. Într-o reţea de transport cUXG ,, orice drum care leagă
intrarea ox cu ieşirea nx conţine cel puţin un arc al unei tăieturi arbitrare )( A .
Cum pentru o tăietură )( A avem Axo şi Axn , rezultă că exista două vârfuri vecine ix şi jx dintr-un drum de la ox la nx ,
astfel încât Axi , Ax j şi )(, Axx ji . Obtinem că pentru a
ajunge în nx , un drum sau lant trece cel puţin printr-un arc dintr-o tăietură arbitrară )( A .
Deoarece no , avem că )(Acn .
Definiţiab 4.1.2. Fie cUXG ,, o reţea de transport. 1) Se numeşte flux maxim în reţeaua de transport G, un flux ,
astfel încât fluxul n care intră în nx să aibă valoare maximă.
2) Un arc Uu al unei reţele de transport cUXG ,, se numeşte saturat dacă )()( ucu .
3) Un flux într-o reţea de transport se numeşte complet, dacă orice drum de la ox la nx conţine cel puţin un arc saturat.
Observaţia 4.1.2. Un flux maxim este complet, dar un flux complet nu este
obligatoriu şi maxim, deoarece el poate fi mărit considerând lanţuri de la ox la nx care nu conţin arce saturate (lanţuri nesaturate)
74
§ 4. 2. Algoritmul Ford-Fulkerson. Flux maxim în reţele de transport
Fie cUXG ,, o reţea de transport impreuna cu un flux
compatibil cu ea, cu 0,0 uc . Fie un drum de la xo la xn. Dacă nu există arc saturat în acest
drum, putem mări fluxul φn cu respectarea condiţiilor de mărginire şi conservare a fluxului. Vom considera 0)()( uucu pentru orice u arc al drumului µ şi fie
uuCum
min .
Pe fiecare arc al drumului µ vom mări fluxul cu αm. Obţinem un flux mărit nmn , păstrându-se condiţiile (m) şi (c).
Dacă avem un lanţ η de la xo la xn, vom nota cu η+ arcele din η având acelaşi sens cu sensul de parcurgere de la xo la xn şi cu η- arcele orientate invers.
Fie mmm
um
um siuuuC
,min)(min,min
.
Pentru γm>0 mărim fluxul cu γm pe fiecare arc u şi-l micşorăm cu γm pe fiecare arc u . Obţinem tot un flux pozitiv ce verifică condiţia (m) şi (c) cu nmn .
Definiţia 4.1.3. Un drum pentru care αm=0 se numeşte saturat, iar un lanţ pentru care γm=0 se numeşte saturat.
Algoritmul Ford-Fulkerson Teorema Ford-Fulkerson. Fie cUXG ,, o reţea pe care
am definit un flux compatibil φ. Dacă nu avem nici un lanţ nesaturat care pleacă din xo şi ajunge la xn, fluxul φn este maxim în xn şi este egal cu capacitatea minimă a unei tăieturi.
75
Demonstraţie. Pasul 1. Se obţine un flux complet pornind de la fluxul iniţial
compatibil cu capacitatea arcelor reţelei. Pentru aceasta, se ia un drum nesaturat de la xo la xn, şi se măreşte fluxul pănă la saturarea a cel puţin unui arc. Se repetă Pasul 1 până când nu mai avem drumuri nesaturate, deci am obţinut un flux complet.
Pasul 2. Se consideră toate lanţurile elementare de la xo la xn. Parcurgând un astfel de lanţ, căutăm un arc u oarecare cu proprietăţile:
u şi 0u . Un astfel de lanţ este saturat şi-l vom elimina. Vom parcurge doar lanţurile nesaturate. Un astfel de lanţ nesaturat îl vom satura mărind fluxul cu γm pentru u şi micşorând cu γm pentru
u până când obţinem γm =0 . Un lanţ nesaturat de la xo la xn îl determinăm prin următorul
procedeu de marcaj. Procedeu de marcaj 1. Marcăm xo cu [+]. Dacă vârful xi a fost marcat, vom nota cu : [+xi] un vârf xj nemarcat dacă (xi , xj)ϵU si dacă (xi , xj) este
nesaturat. [-xi] un vârf xj nemarcat cu proprietatea că arcul (xi , xj) este
traversat de un flux strict pozitiv. Dacă vârful xn a fost marcat, atunci avem un lanţ de la xo la xn
nesaturat, determinat in ordinea parcurgerii etichetelor de la xn la x0, pe care-l putem satura după cum am descris mai sus.
Dacă vârful xn nu a fost marcat, atunci rezultă că nu mai avem lanţ nesaturat de la xo la xn. STOP
Fie A mulţimea vârfurilor nemarcate. Este clar că xnЄA şi Axn , deci A defineşte o tăietură ω-(A). În această situaţie avem
AcucuAuAu
n
)()()()(
În această situaţie obţinem valoarea maximă a fluxului.
76
Deoarece )(Acn pentru orice tăietură şi flux dat, în cazul
nostru avem egalitatea pentru n flux maxim, deci obligatoriu tăietura va fi de capacitate minimă. Deci, dacă nu avem lanţuri nesaturate de la xo la xn , în reţea obţinem un flux maxim.
Algoritmul(F-F max). 1. Se obţine un flux compatibil cu capacităţile arcelor
reţelei, care poate fi iniţial nul. 2. Se obţine un flux complet. Vom considera arcele
nesaturate. Dacă fluxul nu e complet, vom considera un drum format din arce nesaturate, se măreşte fluxul pe arcele acestui drum până la saturarea cel puţin a unui arc. Se repetă până când toate drumurile de la xo la xn sunt saturate.
3. Se obţine un flux maxim prin procedeul de etichetare de mai sus.
4. Algoritmul are un număr finit de paşi deoarece capacităţile şi compoziţia fluxului sunt numere pozitive.
Pentru a usura procedeul de marcaj si pentru a putea programa mai usor acest algoritm, in practica se mai utilizeaza si urmatorul procedeu de marcaj:
Procedeu de marcaj 2. 1) Se ataseaza grafului G=(X,U) un tabel in care pentru
fiecare arc al grafului corespunde o celula avand doua elemente : capacitatea reziduala d=diferenta dintre capacitatea si fluxul arcului respectiv si f fluxul arcului.
d f
2) Se gaseste un lant de la varful x0 la varful xn atribuind
aceeasi eticheta liniilor si coloanelor avand acelasi índice, si anume:
77
- Daca linia xi este marcata, atunci marcam cu (+, i) orice coloana xj in care celula din linia i are capacitatea reziduala pozitiva. Se atribuie aceeasi marca si liniei xj.
- Daca coloana xi este marcata, atunci marcam cu (-, i) orice linie xj in care celula din coloana i are fluxul pozitiv. Se atribuie aceeasi marca si pentru coloana xj.
3) Se defineste fluxul ),(2 u construind un nou tabel. 4) Se continua procedeul pana cand xn un mai poate fi
marcat. 5) Se determina sectiunea minima a retelei, ca fiind formata
din multimea varfurilor nemarcate, capacitatea acestei sectiuni dand valoarea fluxului maxim.
Exemplu. Fie reteaua de transport data in figura de mai jos. Sa se
determine fluxul maxim in varful 8.
Folosind procedeul de marcaj 2, vom avea:
78
0 1 2 3 4 5 6 7 8
0 1
2
0
2
1
2
1 0
3
(+,0)
2 1
1
1
1
(-,1)
3 1
5
(+,2)
4 0
1
1
1
(+,0)
5 0
3
1
2
(+,3)
6 2
1
1
2
(-,7)
7 0
2
(+,4)
8 (+,6)
(+,0) (-,1) (+,2) (+,0) (+,3) (-,7) (+,4) (+,6)
Cu ajutorul procedeului de marcaj, se determina un lant {0,4,7,6,8}, se
modifica fluxurile si capacitatile reziduale corespunzator si obtinem noul
tabel:
79
0 1 2 3 4 5 6 7 8
0 1
2
0
2
0
3
1 0
3
(+,0)
2 1
1
1
1
(-,1)
3 1
5
(+,2)
4 0
1
0
2
5 0
3
1
2
(+,3)
6 3
0
0
3
7 0
2
8 (+,5)
(+,0) (-,1) (+,2) (+,3) (+,5)
Avem lantul {0,1,2,3,5,8}. Noul flux este dat in tabelul:
80
0 1 2 3 4 5 6 7 8
0 0
3
0
2
0
3
1 0
3
2 0
2
0
2
3 0
6
4 0
1
0
2
5 0
3
0
3
6 3
0
0
3
7 0
2
8
Se observa ca, singurul varf care se mai poate marca este varful 0. Multimea varfurilor nemarcate este A={1,2,3,4,5,6,7,8} si determina sectiunea minimala )(A ={(0,1),(0,2),(0,4)}. Capacitatea acestei sectiuni va fi valoarea fluxului maxim: 3+2+3=8.
Program 7. Algoritmul implementat in C++ , varianta 1 de etichetare, este:
81
#include <stdio.h> #define WHITE 0 #define GRAY 1 #define BLACK 2 #define MAX_NODES 1000 #define oo 1000000000 int n; // numarul nodurilor int e; // numarul arcelot int capacity[MAX_NODES][MAX_NODES]; // matricea capacitatilor int flow[MAX_NODES][MAX_NODES]; // matricea fluxurilor int color[MAX_NODES]; int pred[MAX_NODES]; int min (int x, int y) { return x<y ? x : y; } int head,tail; int q[MAX_NODES+2]; void enqueue (int x) { q[tail] = x; tail++; color[x] = GRAY; } int dequeue () { int x = q[head]; head++; color[x] = BLACK; return x; } int bfs (int start, int target) { int u,v; for (u=0; u<n; u++) { color[u] = WHITE; } head = tail = 0; enqueue(start);
82
pred[start] = -1; while (head!=tail) { u = dequeue(); for (v=0; v<n; v++) { if (color[v]==WHITE && capacity[u][v]-flow[u][v]>0) { enqueue(v); pred[v] = u; } } } } //Ford-Fulkerson int max_flow (int source, int sink) { int i,j,u; // Initializeaza flux nul. int max_flow = 0; for (i=0; i<n; i++) { for (j=0; j<n; j++) { flow[i][j] = 0; } } while (bfs(source,sink)) { int increment = oo; for (u=n-1; pred[u]>=0; u=pred[u]) { increment = min(increment,capacity[pred[u]][u]-flow[pred[u]][u]); } for (u=n-1; pred[u]>=0; u=pred[u]) { flow[pred[u]][u] += increment; flow[u][pred[u]] -= increment; } max_flow += increment; }
83
return max_flow; } void read_input_file() { int a,b,c,i,j; FILE* input = fopen("retea3.txt","r"); fscanf(input,"%d %d",&n,&e); for (i=0; i<n; i++) { for (j=0; j<n; j++) { capacity[i][j] = 0; } } for (i=0; i<e; i++) { fscanf(input,"%d %d %d",&a,&b,&c); capacity[a][b] = c; } fclose(input); } int main () { read_input_file(); printf("%d\n",max_flow(0,n-1)); return 0; } Datele din exmplul de mai sus sunt puse in fisierul retea3.txt.
84
Dupa rularea programului, obtinem rezultatul cunoscut:
85
§ 4. 3. Algoritmul Ford-Fulkerson. Flux minim în reţele de transport
Problema fluxului minim intr.-o retea de transport este asemanatoare cu problema fluxului maxim, cu deosebirea ca vom avea o alta conditie de marginire:
Uuucu ),()( (condiţia de mărginire a fluxului). In acest caz, se cauta un flux in retea astfel incat fluxul la iesirea din rete asa fie minim. Definitia taieturii generata de o multime de varfuri A se modifica si ea astfel: O taietura este o multime de arce de forma )(A , cu proprietatea ca xnϵA si )(A . Rezulta ca )(Acn
. Folosind aceleasi notatii ca si in cazul maxim, avem urmatorul procedeu de obtinere a unui flux minim.
Algoritmul(F-F min).
1) Se obţine un flux compatibil cu capacităţile arcelor reţelei. Se alege un astfel de flux astfel incat sa se respecte conditia de conservare in nodurile retelei si pe fiecare arc fluxul sa fie mai mare sau egal cu capacitatea arcului. Consideram diferite drumuri de la intrare la iesire pe care definim un flux superior capacitatilor tuturor arcelor.
2) Se obţine un flux complet. Se diminueaza fluxul pe arcele drumurilor de la xo la xn astfel incat fiecare drum sa contina un arc nesaturat.
3) Se obţine un flux minim prin procedeul de etichetare de mai jos.
Procedeu de etichetare. Marcăm xo cu [-]. Dacă vârful xi a fost marcat, vom nota cu : [-xi] un vârf xj nemarcat cu proprietatea ca arcul (xi , xj)ϵU
este nesaturat, deci ).()( ucu
86
[+xi] un vârf xj nemarcat cu proprietatea că arcul (xi , xj) este in retea.
Daca prin acest procedeu de etichetare, se marcheaza varful xn atunci un astfel de lanţ nesaturat îl vom satura micsoran cu γm fluxul pentru u şi marind cu γm pentru u . Se repeat acest procedeu pana candnu va mai fi posibila etichetarea.
87
CAPITOLUL 5
ARBORI
Un arbore este un graf conex şi fǎrǎ cicluri. O pǎdure este un graf pentru care fiecare componentǎ conexǎ este un arbore. Numim numarul ciclomatic al unui graf, numarul )(G = m – n + p 0, unde m este numarul muchiilor, n numarul varfurilor si p numarul componentelor conexe din graful G. Acest numar ne arata cate cicluri sunt in acel graf Observaţia 5. 1. Noţiunea de arbore se referǎ la 1 – grafuri sau la grafuri neorientate, ambele fǎrǎ muchii multiple. În studiul arborilor orientarea arcelor nu are importanţǎ. Propoziţia 5.2. Fie G = (X,U) un graf cu 2|| nX Sunt echivalente afirmaţiile: i) G este arbore. ii) G este conex şi minimal cu aceastǎ proprietate. iii) G este fǎrǎ cicluri şi maximal cu aceastǎ proprietate. Dacǎ
se adaugǎ un arc între orice douǎ vârfuri neadiacente avem un ciclu unic.
iv) G este fǎrǎ cicluri şi are n – 1 arce. v) G este conex şi are n – 1 arce. vi) Pentru orice douǎ vârfuri distincte ale lui G existǎ un singur
lanţ care le uneşte. Demonstraţie. i) ii) Fie Uyxe ),( o muchie din G. Din i) avem cǎ G este conex. Fie graful G – {e}.
88
Dacǎ acesta rǎmâne conex rezultǎ cǎ avem drum între vârfurile x şi y în G – {e} ceea ce implicǎ existenţa unui ciclu în graful G contradicţie. ii) i) Arǎtǎm cǎ G nu are circluri. Presupunem cǎ existǎ un ciclu şi e = uv o muchie din ciclu . Fie d un drum arbitrar în G, dacǎ e nu este muchie din acest drum, atunci d este din G – e. Dacǎ e este muchie în d, atunci putem obţine un drum în G – e astfel: în loc de e în d punem drumul e , care determinǎ în G – e un drum cu aceleaşi extremitǎţi ca şi d în G, deci G – e este conex. i v) G fiind conex şi fǎrǎ cicluri, resulta ca numarul ciclomatic este zero. Deci, p = 1 şi m – n +1 = 0 m = n –1 Analog i) iv). v) )iii p = 1, m = n – 1 0)( G şi G este fǎrǎ cicluri, dacǎ se mai adaugǎ o muchie, atunci avem un nou graf G’ şi 1)( ' G şi deci ciclul este unic. iii) ii) Dacǎ ar exista douǎ vârfuri nelegate prin nici un lanţ atunci nu am putea avea un ciclu prin adǎugarea unui arc între ele. Deci G este conex. Dacǎ din G suprimǎm un arc, e = (x,y) iar graful G – e este conex, atunci în G – e existǎ, un lanţ de la x la y care împreunǎ cu e genereazǎ un ciclu în G, fals. ii) )vi Dacǎ avem vârfurile x şi y legate prin douǎ lanţuri distincte în graful G, atunci unul din ele conţine o muchie e care nu o are celǎlalt şi dacǎ o suprimǎm, graful G - e este conex, fals. vi) i) Rezultǎ cǎ G este conex şi fǎrǎ cicluri, pentru cǎ existenţa unui ciclu ar însemna cǎ douǎ vârfuri din acel ciclu ar fi unite prin 2 lanţuri distincte. Propoziţia 5.3. Orice graf conex G = (X,U) admite ca graf parţial un arbore H = (X,V), numit arbore parţial al grafului G. Demonstraţie. Conform Propoziţiei 5.2. ii), acest arbore parţial se obţine suprimând muchii din G cu condiţia sǎ se obţinǎ tot grafuri conexe. Definiţia 5.4. i) Fie G un graf şi Xv astfel încat pentru orice alt vârf Xw existǎ drum în graful G de la v la w. Vârful v se numeşte rǎdǎcinǎ a grafului G.
89
ii) O arborescenţǎ este un arbore cu radǎcinǎ. iii) Fie G un graf neorientat şi conex G = (X,U) cu |X| = n. Funcţia l:U R+se numeşte costul muchiei u. Din Propoziţia 5.2., avem cǎ G admite un arbore parţial şi acesta este arbore minim (sau arbore de cost minim) dacǎ suma lungimilor muchiilor sale este minimǎ.
Algoritmul lui KRUSKAL (1956)
Se selecteazǎ cea mai scurtǎ muchie din graful G. Apoi, dintre muchiile rǎmase se alege o muchie care nu formeazǎ cicluri cu cele deja alese şi are lungimea cea mai micǎ. Algoritmul continua pânǎ se selecteazǎ n – 1 muchii. Algoritmul lui Kruskall se aplicǎ pentru un graf neorientat arbitrar G = (X,U). Când G este conex ştim cǎ acest arbore existǎ. Când G nu este conex se descompune în componente conexe iar algoritmul va avea urmǎtoarea formǎ: 1) Ordonǎm muchiile grafului în ordine crescǎtoare a costurilor
sale. 2) O muchie va fi selectatǎ daca are lungimea cea mai scurtǎ dintre
cele neselectate şi care are capetele în componente conexe diferite (şi se uneşte cu celelalte).
Exemplu. Sa se determine arborele minim pentru urmatorul graf, cu lungimile muchiilor date in tabelul de mai jos.
1 2 3 4 5 6 7 8 1 0 6 4 11 5 10 9 13 2 6 0 4 5 7 5 8 10 3 4 4 0 6 3 3 4 6 4 11 5 6 0 9 2 7 6 5 5 7 3 9 0 12 2 3 6 10 5 3 2 12 0 11 7 7 9 8 4 7 2 11 0 3 8 13 10 6 6 3 7 3 0
90
Aplicand algoritmul Kruskal, se selecteaza, mai intai, muchiile (4, 6 ) si (5, 7) de lungime 2, apoi muchiile (3, 5), (3,6), (7, 8) sau (5, 8) de lungime 3, apoi muchiile (1, 3) si (2, 3) de lungime 4. Acest graf are doi arbori minimi, de lungime 21, dati in figura de mai jos.
Algoritmul lui Prim (1957)
Algoritmul lui Kruskal selecteazǎ muchiile. Acest algoritm selecteazǎ vârfurile dint G, construind la fiecare pas i un subgraf partial Ki . 1) Se alege un vârf oarecare x al grafului G şi definim K1 = {x}. 2) Determinǎm cel mai apropiat vârf de x, notat y. Arborele
)}.,{(,},,{X},U,{X K 222222 yxUUUyx 3) Presupunem cǎ la pasul i am obţinut arborele Ki, atunci arborele Ki+1 se obţine din Ki la care se mai adaugǎ nodul yi, neselectat, cu proprietatea cǎ este cel mai apropiat de Ki, cât şi muchia de lungime minimǎ dintre cele care unesc pe yi cu vârfurile din Ki Dupǎ n paşi arborele Kn va conţine toate vârfurile grafului G, deci va fi un arbore parţial al lui G. Algoritmul ia sfârşit ca şi în cazul algoritmului Kruskal si se aratǎ cǎ arborele Kn este arbore parţial minim.
91
Exemplu. Folosind acelasi exemplu ca la algoritmul Kruskal, daca aplicam algoritmul lui Prim, obtinem sistemul de muchii: (1, 3), (3, 5), (5, 7), (3, 6), (6, 4), (7, 8) sau (5, 8), (2, 3), corespunzator tot celor doi arbori. Program 8. Algoritmul Prim, implementat in C++, este:
#include <stdio.h> int n; /* numarul varfurilor in graf */ int weight[100][100]; /* weight[i][j] este lungimea muchiei (i, j) */ char inTree[100]; int d[100} int whoTo[100]; void updateDistances(int target) { int i; for (i = 0; i < n; ++i) if ((weight[target][i] != 0) && (d[i] > weight[target][i])) { d[i] = weight[target][i]; whoTo[i] = target; } } int main(int argc, char *argv[]) { FILE *f = fopen("dist2.txt", "r"); fscanf(f, "%d", &n); int i, j; for (i = 0; i < n; ++i) for (j = 0; j < n; ++j) fscanf(f, "%d", &weight[i][j]); fclose(f); /* infinit= 100000*/ for (i = 0; i < n; ++i) d[i] = 100000; for (i = 0; i < n; ++i) inTree[i] = 0; printf("Adauga nod %c\n", 0 + 'A'); inTree[0] = 1; updateDistances(0);
92
int total = 0; int treeSize; for (treeSize = 1; treeSize < n; ++treeSize) { int min = -1; for (i = 0; i < n; ++i) if (!inTree[i]) if ((min == -1) || (d[min] > d[i])) min = i; printf("Adauga muchie %c-%c\n", whoTo[min] + 'A', min + 'A'); inTree[min] = 1; total += d[min]; updateDistances(min); } printf("Lungimea minima: %d\n", total); return 0; } Utilizand Programul 8, cu datele stocate in fisierul dist2.txt,
in urma rularii, obtinem rezultatul cunoscut
93
Aplicaţii în informaticǎ
Sistemul de operare al unui calculator accepta cereri din diverse surse, cereri care pot sa nu aiba aceeasi prioritate. De exemplu, de mare prioritate sunt anumite procese ale sistemului de operare fata de diverse comenzi ale utilizatorilor dintr-o retea. Pe langa acestea, mai putem avea si transmiterea unor date, efectuarea unor calcule lungi, acestea fiind implementate sa ruleze cu prioritate mica. Operatiile pot fi reprezentate cu un ID pentru operatie si un numar intreg pentru prioritate. Cand este initiata o noua operatie, este gasit ID-ul pentru operatie si prioritatea acesteia. Se executa operatia cu prioritatea cea mai mare. Cand procesorul devine disponibil, sistemul cauta o noua operatie de prioritate maxima, care se executa imediat.
Organizarea unei multimi sub forma unei gramezi, simuleaza foarte bine situatia descrisa mai sus.
94
1) Grǎmezi
Vârfurile terminale într-un arbore se numesc frunze. In cazul arborilor binari, nici un drum de la rǎdǎcinǎ la un alt vârf nu este mai mare ca ][log 2 n . Un arbore parţial ordonat este un arbore binar în care vârfurile au primit câte o etichetǎ. Aceste etichete pot reprezenta de exemplu valoarea unui element sau valoarea anumitor componente ale unui element. Etichetele sunt ordonate în funcţie de prioritǎţi. Eticheta unui vârf are prioritate mai mare decât cea a etichetelor ataşate descendenţilor acelui nod. Fie H = (X,U) un arbore a.î. vârfurile sale au fost etichetate {1,2,...,n} cu 1 rǎdǎcina. Muchiile sunt definite astfel: pentru
orice ni ,2 , avem ca Uii
2
. Acest arbore este parţial
ordonat. Vârfurile lui sunt dispuse pe s+1 nivele, ][log 2 ns , Nivelul },....0{ si conţine toate vârfurile aflate la distanţa i de radǎcina 1. Pe fiecare nivel i avem 2i vârfuri, cu excepţia ultimului nivel. Definiţia 5.5. O mulţime total ordonatǎ, ),,( H
},...,,{ 21 naaaH formeazǎ o grǎmadǎ binarǎ dacǎ pentru orice
2
},....,2{ ii aani .
Acesteia îi putem ataşa arborele H descris mai sus punând în fiecare nod i elementul ai. Deci, valoarea fiecǎrui vârf este mai micǎ sau egalǎ decât cea a descedenţilor sǎi. În general, descendentul stâng al nodului ai este a2i şi cel drept, dacǎ existǎ, este a2i+1. Fie },...,,{ 21 naaaH o mulţime. Ne propunem sǎ organizǎm aceastǎ mulţime ca o grǎmadǎ. Acest lucru îl facem inserând un element într-o gramada deja existentǎ. Pornim de la o grǎmadǎ cu un singur element şi continuǎm pânǎ introducem toate cele n elemente.
95
Exemplu. Sa se organizeze ca o gramada urmatoarea multime: 1 2 3 4 5 6 7 8 9 10 11 18 18 9 9 16 3 7 1 7 5 20 Rezolvare. Avem ca A(1)>A(2), A(1)>A(3), A(2)>A(4), A(2)>A(5), A(3)>A(6), A(3)>A(7), A(4)>A(8), A(4)>A(9), A(5)>A(10) dar A(5)<A(11), deci vom schimba intre ele elementele din pozitiile 5 si 11. Obtinem: 1 2 3 4 5 6 7 8 9 10 11 18 18 9 9 20 3 7 1 7 5 16 Avem ca A(1)>A(2), A(1)>A(3), A(2)>A(4) dar A(2)<A(5), deci vom schimba intre ele elementele din pozitiile 2 si 5. Obtinem:
1 2 3 4 5 6 7 8 9 10 11 18 20 9 9 18 3 7 1 7 5 16 Avem ca A(1)<A(2), deci vom schimba intre ele elementele din pozitiile 1 si 2. Obtinem: 1 2 3 4 5 6 7 8 9 10 11 20 18 9 9 18 3 7 1 7 5 16 Avem ca A(1)>A(2), A(1)>A(3), A(2)>A(4), A(2)>A(5), A(3)>A(6), A(3)>A(7), A(4)>A(8),A(4)>A(9),A(5)>A(10) dar A(5)>A(11), deci am organizat multimea ca o gramada. Arborele asociat este:
A=
A=
A=
A=
96
Programul 9. Implementarea in C++este
#include <iostream> #include <algorithm> #include <functional> #include <vector> using namespace std; int main() { const int VECTOR_SIZE = 10 ; typedef vector<int > IntVector ; typedef IntVector::iterator IntVectorIt ; IntVector Numbers(VECTOR_SIZE) ; IntVectorIt it ; // Introducerea numerelor Numbers[0] = 4 ;
97
Numbers[1] = 10; Numbers[2] = 70 ; Numbers[3] = 10 ; Numbers[4] = 30 ; Numbers[5] = 69 ; Numbers[6] = 96 ; Numbers[7] = 100; Numbers[8] = 100; Numbers [9] = 98; // printarea continutului din Numbers cout << "Numbers { " ; for(it = Numbers.begin(); it != Numbers.end(); it++) cout << *it << " " ; cout << " }\n" << endl ; // transformarea Numbers intr.-o gramada make_heap(Numbers.begin(), Numbers.end()) ; cout << " Transforma in gramada\n" << endl ; cout << "Numbers { " ; for(it = Numbers.begin(); it != Numbers.end(); it++) cout << *it << " " ; cout << " }\n" << endl ; // sortare pentru Numbers sort_heap(Numbers.begin(), Numbers.end()) ; cout << "Sorteaza \n" << endl ; // printare Numbers cout << "Numbers { " ; for(it = Numbers.begin(); it != Numbers.end(); it++) cout << *it << " " ; cout << " }\n" << endl ; }
98
Ruland pentru exemplul de mai sus, obtinem rezultatul cunoscut:
2) Probleme de sortare-cǎutare. Fie H = (X,U) un arbore binar şi ),( A o mulţime total ordonatǎ finitǎ. H este arbore de binar de sortare-căutare pentru A dacǎ avem datǎ o etichetare a vârfurilor (aplicaţia ),: bijectivăeAXE astfel încât pentru orice Xx , orice y din subarborele stâng al lui x are
)()( xEyE şi orice z din subarborele drept al lui x are )()( xEzE . Probleme de sortare
Ne propunem sǎ ordonǎm crescǎtor mulţimea A comparând câte douǎ elemente, },...,,{ 21 naaaA . Vom construi un arbore binar de sortare-cǎutare. Elementul a1 va fi eticheta rǎdǎcinii. Elementul a2 se comparǎ cu a1, dacǎ e mai mic sau egal va fi descendent stâng, dacǎ este strict mai mare va fi descendent drept. Fie elementul ai . Se comparǎ cu a1, dacǎ este 1a va face parte din subarborele sǎu stâng, dacǎ este > a1, va face parte din subarborele drept al lui a1.
99
Se continua procedeul pânǎ când am ajuns la elementul n. Ordinea este datǎ de parcurgerea arborelui obţinut în inordine (fiul stâng, rǎdǎcinǎ, apoi fiul drept). În felul acesta putem determina minimul ca fiind cea mai din stânga frunzǎ şi maximul mulţimii A, ca fiind cea mai din dreapta frunzǎ.
Probleme de cǎutare a) Apartenenţa la o submulţime B, a unui element ABAx , Fie BxAx , ? Se asociazǎ mulţimii B arborele, de sortare- cǎutare. Acesta se parcurge din rǎdǎcinǎ comparând elementul x cu valoarea asociatǎ nodului curent, pânǎ ajungem la concluzia cǎ Bx Dacǎ Bx , atunci x devine o frunzǎ pentru arborele ataşat. b) Inserţia unui element. Se parcurge arborele pornind de la
rǎdǎcinǎ (în inordine) pânǎ se ajunge într-o frunzǎ, ataşând acest element frunzei ca fiu drept sau stâng.
c) Ştergerea unui element a. Se determinǎ nodul x etichetat cu a. Dacǎ este frunzǎ, atunci se şterge x din arbore. Dacǎ x are doar un descendent y se face legǎtura dintre pǎrintele lui x cu y şi ştergem apoi pe x. Dacǎ x are doi descendenţi, cǎutǎm în subarborele drept al lui x nodul y în care se aflǎ cel mai mic element b care este de fapt succesorul imediat al lui a. Se înlocuieşte în x valoarea a cu b şi ştergem nodul y. Ştergerea lui y se face uşor deoarece el este frunzǎ sau are doar descendent drept.
3) Parcurgerea arborilor
Se poate face în :
Inordine- se parcurge mai întâi fiul stâng, rǎdǎcina şi la urmǎ
fiul drept(S-R-D). Parcurgerea se face astfel : se trece eticheta unui nod
dupa explorarea subarborelui stang, dar inainte de explorarea
100
subarborelui drept. Ne da forma expresiei, dar fara paranteze.(expresie
infix)
Postordine – se parcurge întâi descendentul stâng, apoi cel drept
şi la urmǎ rǎdǎcina(S-D-R). Parcurgerea se face astfel: daca un nod a
fost vizitat, se vor trece mai intai etichetele descendentilor sai, pornind
cu cei din stanga, apoi cei din dreapta si la urma nodul.(expresie postfix)
Preordine – se parcurge întâi rǎdǎcina, descendentul stâng şi
apoi cel drept(R-S-D). Parcurgereea se face astfel: se viziteaza nodul si
ceilalti descendenti ai sai, scriind etichetele in functie de prima intalnire
a nodului pornind da la radacina si parcurgand arborele in sens invers
acelor de ceasornic. Vom nota doar etichetele acelor noduri carea u fost
prima data vizitate.(expresie prefix)
Construirea expresiei infix pornind de la expresia prefix sau
de la expresia postfix. Facem mai intai observatia ca operatorii
{+, -, /, *} au un numar fix de operanzi, de obicei 2. Deci, un e nevoie sa
folosim intotdeauna paranteze decat daca avem un numar ambiguu de
operatori si operanzi.
Pentru o obtine infix pornid de la prefix, gasim un operator care
este urmat de numarul cerut(stiut) de operanzi fara a include alti
operatori. Se noteaza acea subexpresie si se continua procedeul.
Pentru a obtine infix pornind de la postfix, gasim in expresia
postfix un operator precedat de numarul cerut de operanzi fara a include
alti operatori. Se noteaza acea subexpresie si se continua procedeul.
101
Evaluarea expresiilor algebrice Orice expresie algebrică poate fi memoratǎ sub forma unui arbore binar. Operatorii care apar }/,,*,{ au o anumitǎ prioritate în efectuarea calculelor. De exemplu, sǎ considerǎm expresia
aedcb *)*)(( . Arborele binar asociat va fi * a + b * _ e c d (Nodurile arborelui vor fi etichetate fie cu operatori fie cu operanzi) Dacǎ parcurgem acest arbore în inordine, obţinem: b+c-d*e*a Dacǎ parcurgem acest arbore în postordine obţinem: bcd-e*+a* Dacǎ parcurgem acest arbore în preordine obţinem: *+b*-cdea
Exemplu. Convertiti expresia ab+c*de-/f+ din postfix in infix si
prefix.
Rezolvare. Pentru expresia data in postfix, avem ab+c*de-/f+.
Notam y=ab+ si obtinem expresia yc*de-/f+. Notam z=yc*, si obtinem
expresia zde-/f+. Notam w=de- si avem expresia zw/f+. Notam
t=zw/ si avem expresia tf+, adica t+f, rezulta (z : w)+f →(z:(d-e))+f
→ ((y*c):(d-e))+f → ((a+b)*c):(d-e))+f.
Expresia in infix, va fi ab*c:d-e+f
102
Arborele asociat va fi:
Parcurgem in preordine(R-S-D) si obtinem +/*+abc-def.
103
CAPITOLUL 6
PROBLEME DE COLORARE Definitia 6.1. Fie G=(X,U) un graf neorientat. Numǎrul cromatic al unui graf G, notat )(G , este numǎrul minim de culori necesare pentru colorarea vârfurilor grafului, astfel încât douǎ vârfuri adiacente sǎ nu fie colorate cu aceeaşi culoare. Definiţia 6.2. Fie },...2,1{)( piiA o partiţie a mulţimii de vârfuri X. Spunem cǎ partiţia },...2,1{)( piiA este o colorare cu p culori sau este o p-colorare a vârfurilor dacǎ şi numai dacǎ orice douǎ vârfuri din Ai nu sunt adiacente. În aceastǎ situaţie graful se numeşte p-cromatic. Observatia 6.3. Putem spune cǎ )(G este numǎrul minim de culori pentru care avem o )(G - colorare a grafului G. Vom nota cu )(GN r numarul r-colorǎrilor distincte a vârfurilor unui graf G şi cu Rtrtttttr ),1)...(2(|)1( .
Definiţia 6.4. Polinomul k
nt
kk tGNtGP )(),(
1
se numeşte polinomul
cromatic asociat grafului G si reprezintǎ numarul r colorarilor grafului trG , .
Propozitia 6.5. Fie *Nq , atunci P(G,q) este numǎrul de colorǎri ale vârfurilor unui graf utilizând q culori. Demonstraţie. Orice k-colorare presupune utilizarea a k culori din cele maxim q culori date, deci, în total, numǎrul lor este
104
)1)...(1( kqqqAkq . Deci numǎrul total de q-colorari a vârfurilor
cu q culori este k
n
kk qGN )(
1
.
Reciproc, orice colorare a vârfurilor grafului G în qk culori determinǎ o partiţie a lui G în k- clase de colorare. □ Observaţie 6.6.
1) Dacǎ G are n vârfuri, atunci 0)( GNk pentru k > n, 1)( GN n si deci ),( tGP este monic.
2) Dacǎ G are 2 componente conexe C1 şi C2 , putem avea pentru vârfurile din C1 şi C2 colorǎri independente, deci
).,(),(),( 21 qCPqCPqGP
Propoziţia 6.7. Fie G=(X, U) un graf neorientat. Sǎ se arate cǎ ,)1(),( )(|| VCV
UVqqGP
unde C(V) reprezintǎ numǎrul de componente
conexe ale are graful parţial al lui G, GV=(X,V). Demonstraţie. Dacǎ X este mulţimea vârfurilor X cu |X|=n, V={v1,...,vn} atunci o q-colorare a grafului G este o funcţie
,,1},...,1{ NqqcuqXk cu proprietatea cǎ dacǎ )()(),( yKxKUxx ji .
Fie )()(|},...,1{:{ ykxkqXkM i , pentru }},{ Uyxui . Atunci, |...|),( 21 n
n MMMqqGP . Folosim principiul inducerii şi al excluderii, avem:
m
i mji
m
ii
mjiim MMMMMMM
1 1 121 ||)1(...||||...| ,
unde
m
iiM
1|| reprezintǎ numǎrul tuturor funcţiilor care au aceeaşi
valoare din multimea {1,2,...,q} pentru extremitatile fiecarei muchii din V={ui}, GV={X, V} graf parţial al lui G cu o singurǎ muchie. In aceastǎ situaţie GV are n-1 componente, iar aceste functii iau o aceeasi valoare din {1, 2, …,q} pentru fiecare component conexa a grafului GV , deci
105
qn-1 functii. Mai departe, avem ca mji
ji MM1
este numarul functiilor
care au aceeasi valoarea din {1, 2, …,q} pentru fiecare componenta conexǎ a unui graf parţial al lui G cu numai 2 muchii adiacente sau nu, deci avem, in total, n-2 componente conexe, deci qn-2 functii. Rezultǎ cǎ
mji
ji MM1
=qn-2, s.a.m.d., n
ii qM
1
||
pentru cǎ avem o singura
componenta conexǎ. Deci
||
)(||)1(),(V
UV
VCV qqGP , unde C(V) sunt componentele conexe
ale grafului parţial (X,V).□ Existǎ algoritmi ce calculeazǎ polinomul cromatic al unui graf. Fie G=(X,U), un graf arbitrar, yxyxeUe ),,(, o muchie a sa. Vom nota cu G-{e} graful obţinut din G prin eliminarea muchiei e,
}){,(}{ eUXeG şi cu Ge graful obţinut din G prin eliminarea vârfurilor x şi y şi a muchiilor incidente cu aceste vârfuri şi înlocuirea acestora cu un vârf unic z(x,y), care se va uni cu toate vârfurile din G care erau adiacente fie cu x, fie cu y, fie cu ambele. Ge se numeşte contracţia grafului G. Se observǎ G-{e} are o muchie mai puţin decât G iar Ge are o muchie şi un vǎrf mai puţin decât graful G. Propoziţia 6.8. Cu notaţiile mai sus, sǎ se arate cǎ
),()},{(),( qGPqeGPqGP e . Demonstraţie. Dacǎ funcţia },...2,1{: qXk este o q-colorare a grafului G, deoarece k(x) ≠ k(y) pentru orice muchie e = (x,y), rezulta ca aceasta este o q-colorarepentru graful G-{e} si reciproc, deci
),()},{( qGPqeGP reprezinta numarul colorarilor k din G-{e} cu e=(x,y) si k(x) = k(y). Fie K o colorare a grafului G-{e}, e={x,y} si k(x) = k(y). Ea produce o q-colorare k’ a grafului Ge astfel: definim k’(z)=k(x)=k(y) si k’(t)≠k(t), pentru orice t≠z. Reciproc, orice q-colorare k’ a grafului Ge induce o q-colorare k a grafului G-{e} cu k(x) =k(y), daca definim k(x) = k(y) = k’(z) si k(t) = k’(t), pentru orice t≠x, y. Deci, ),(),()},{( qGPqGPqeGP e ,
106
pentru orice q numar natural. Ambii membri ai acestei egalităţi sunt polinoame, deci egalitatea este valabilă pentru orice q □
Algoritmul lui Zykov (pentru determinarea numărului cromatic
al unui graf).
Mai întâi facem următoarea observaţie. Dacă G este un graf şi G’
un subgraf al său, orice q-colorare a vârfurilor lui G induce o q-colorare
a vârfurilor lui G’, deci γ(G’)≤ γ(G), deci γ(G)≥ω(G), unde prin ω(G) am
notat cardinalul maxim al unei clici (graf simplu neorientat şi complet).
Algoritmul
Considerăm graful G cu x,y două vârfuri neadiacente. Fie
Γ=G{e}, graful obţinut din G prin introducerea arcului e=(x,y) şi Γe
contracţia grafului Γ, Din cele de mai sus, (dacă luăm în locul grafului
G-{e}, graful G), obţinem:
γ (G)=min(γ (G{e}), γ (Ge))
Se consideră separat grafurile G{e} sau Ge şi se repeta acest
procedeu până se obţin grafuri care sunt clici. Pentru clici, numărul
cromatic este egal cu numărul de vârfuri. Atunci numărul cromatic va fi
egal cu numărul maxim de vârfuri din G care pot forma o clică.
Acest algoritm este destul de greu de utilizat practic, deoarece
apar foarte multe grafuri care sunt analizate si mai este cunoscut şi sub
numele de algoritmul legărilor şi contracţiilor.
Un alt algoritm folosit în colorarea vârfurilor unui graf, este
algoritmul greedy de colorare. Descrierea acestui algoritm este
următoarea:
1) Se fixează o ordine de parcurgere a vârfurilor grafului.
107
2) Se atribuie primului vârf culoarea 1 şi se parcurge mulţimea
vârfurilor astfel ordonată. Pentru un vârf se determină, “cea
mai mică” culoare k, dintre cele date până la momentul
respectiv, care i se poate atribui, astfel încât acest vârf să nu
poată fi adiacent cu nici un vârf care este colorat cu culoarea
k.
3) Dacă o astfel de culoare nu există, se măreşte mulţimea
culorilor cu o culoare distinctă de cele deja existente, iar
vârfului i se va atribui această culoare.
Acest algoritm determină, în general, o q-colorare a grafului, care
depinde de ordinea de parcurgere a vârfurilor grafului şi nu numărului
cromatic. Numărul cromatic va rezulta atunci când ordinea de parcurgere
a vârfurilor grafului este dată de o permutare care are anumite
proprietăţi.
Exemplu. Sa se determine numarul cromatic pentru graful de mai jos, folosind algoritmul lui Zykov.
Rezolvare.
108
Aceasta a fost pentru graful Γ . Pentru graful Γe, avem:
109
Deci, numarul cromatic este 3, varfurile d si b pot fi colorate cu culoarea c1, varfurile e si a cu culoarea c2, varfurile f si c cu culoarea c3.
110
BIBLIOGRAFIE [1] Alfred V. Aho, Jeffrey D. Ullman, Foundations of Computer Science, Computer Science Press, New York, 1995. [2] R. K. Ahuja, T. L. Magnati, J. B. Orlin, Network flows : theory, algorithms and applications, Prentice Hall Inc., New York, 1993. [3] J. Bang-Jensen, G. Goutin, Digraphs: Theory, Algorithms and Applications, Springer-Verlag, London, 2000. [4] C. Berge, Théorie des graphes et ses applications, Dunod, Paris, 1967. [5] N. Biggs, Algebraic graph theory, Cambridge University Press, 1974. [6] Cristina Flaut, Algoritmica grafurilor, Ovidius University Press, Constanta, 2009, ISBN:978-973-614-438-7. [7] Cristina Flaut, Florian Ghionea, Some properties of the line graph associated to a graph G, Italian J. of Pure and Applied Mathematics, nr. 25(2008), pag. 165-174. [8] Cristina Flaut, Florian Ghionea, Monica Parvan, Optimization of urban transportation network, Mathematics and Computer in Business and Economics, Proceedings of the 9th WSEAS International on Mathematics and Computer in Business and Economics(MCBE’ 08), Bucuresti, 24-26 iunie 2008, pag. 111-116. [9] Florian Ghionea, Cristina Flaut, An optimization of a transportation problem, Metalurgia International, 13(1)(2008), index CNCSIS 480.
111
[10] P. Grossman, Discrete Mathematics for Computing, Palgrave MacMillan, New York, 2002. [11] O. Ore, Theory of graphs, AMS, Rhode Island, 1962. [12] Monica Parvan, Florian Ghionea, Cristina Flaut, A mathematical model of the relevant request determination in the transport problem, Mathematics and Computer in Business and Economics, Proceedings of the 9th WSEAS International on Mathematics and Computer in Business and Economics(MCBE’ 08), Bucuresti, 24-26 iunie 2008, pag. 105-111 [13] H. R. Radian, T. J. Radian, Recreaţii matematice, Editura Albatros, Bucureşti, 1973 [14] Nicolae Rădescu, Eugenia Rădescu, Probleme de teoria grafurilor, Scrisul Romanesc, Craiova, 1982. [15] E. Tanaguchi, City logistic, Pergamon, Amsterdam, 2001. [16] I. Tomescu, Combinatorică şi Teoria Grafurilor, Bucureşti, 1978. [17] Tutorial C++, http://www.cplusplus.com/files/tutorial.pdf [18] C-Free software, http://download.cnet.com/3001-2212_4-10311060.html?spi=3ad87158cf60b9f08d5dfad7f61e9c38&part=dl-6261022