Sunteți pe pagina 1din 40

Elemente de teoria grafurilor

Scurt istoric

Data naçterii teoriei grafurilor poate fi consideratå anul 1736, c`nd


matematicianul Leonnard Euler a publicat în revista Comenta di Academiae
Scientiarum Imperialis Petropolitanae un articol în limba latinå (Solutio
problematio ad geometrian situs pertinentis - Solu\ia unei probleme legate de
geoemtria de pozi\ie) în care a clarificat problema celor 7 poduri, stabilind astfel o
metodå de rezolvare a unei intregi clase de probleme. Articolul lui Euler a fost
tradus çi publicat în revista Nuvelles Annales de Mathematiques în anul 1851,
fåc`nd astfel posibilå dezvoltarea acestui domeniu. Ca izvoare ale teoriei grafurilor
mai pot fi considerate fizica - studiul re\elelor electrice, geografia - problema
colorårii hår\ilor cu mai mult de 4 culori, chimia.
Teoria grafurilor este o ramurå destul de nouå a teoriei mul\imilor care s-a
dovedit foarte utilå çi cu aplica\ii în domenii variate: economie, chimie organicå,
organizare, psihologie, anumite domenii ale artei, etc.
Grafurile oferå cele mai potrivite metode de a exprima rela\ii între obiecte,
de aceea aria lor de utilizare practicå este foarte vaståde la economie, la psihologie
socialå.

No\iuni de bazå

Så consideråm mul\imile finite X =  x1, x2, . . . xn çi mul\imea U care este


produsul cartezian al mul\imii X cu ea însåçi.
Defini\ie: Se numeçte graf o pereche ordonatå de mul\imi (X,U), X fiind o
mul\ime finitå çi nevidå de elemente numite v`rfuri sau noduri, iar U o mul\ime de
perechi (submul\imi cu douå elemente) din X numite muchii sau arce.
Mul\imea X se numeçte mul\imea nodurilor sau v`rfurilor grafului, iar
mul\imea U - mul\imea muchiilor sau arcelor.
Un graf va fi notat cu G = (X,U), iar în figurarea sa, v`rfurile (nodurile) se
vor reprezenta prin numere sau litere , muchiile prin linii neorientate, iar arcele prin
linii orientate.
Mai departe, vom face o separare (clasificare a grafurilor). Am aråtat în
definirea lor cå elementele componente ale grafului sunt X çi U, deci v`rfuri sau
noduri çi muchii sau arce. Observåm cå, în reprezentarea unei muchii (arc), U are
elementele  xI, xk   U. Aceste elemente sunt extremitå\ile muchiei. Dar observåm
cå muchia U cu  xi, xk   U este aceeaçi cu  xk, xi   U (ne este eviden\iatå aici
prorietatea de simetrie).

Defini\ie: Se spune cå mul\imea U are proprietatea de simetrie dacå çi numai


dacå av`nd  xi, xk   U, rezultå  xk, xi   U.

Func\ie de aceastå proprietate (de simetrie) ce apare la elementele ce


definesc muchiile, grafurile se împart în douå categorii:
- Grafuri neorientate
- Grafuri orientate

Grafuri Neorientate

Defini\ie: Se numeçte graf neorientat o pereche ordonatå de mul\imi (X,U)


unde:
- X este o mul\ime finitå çi nevidå de elemente numite v`rfuri sau noduri;
- U este o mul\ime de pereche neorientate de c`te douå elemente din X,
numite muchii sau arce.
Dacå mul\imea U are proprietatea de simetrie, se spune cå graful G=(X,U)
este graf neorientat.

Pentru G= (X,U) graf neorientat, o muchie U senoteazå cu  xI, xk  çi este o


pereche neordonatå de v`rfuri distincte din X (adicå XI, Xk  X çi XI  Xk).
V`rfurile XI, Xk se numesc extremitå\ile muchiei U. Se spune cå v`zzrfurile
XI çi Xk sunt v`rfuri adiacente în graful G.
Dacå un v`rf un este extremitatea nici unei muchii, el se numeçte v`rf izolat.
Dacå un v`rf este extremitatea unei singure muchii, el se numeçte v`rf terminal.
Consideråm muchia U notatå XI, Xk; se spune cå v`rfurile XI çi Xk sunt
incidente cu muchia XI, Xk. De asemenea, despre douå muchii care au o
extremitate comunå, se spune cå sunt incidente.

Exemplu:

Fie graful G=(X, U) din figura 1, av`nd X=1,2,3,4,5,6,7 - mul\imea


v`rfurilor çi U=U1,U2,U3,U4,U5 - mul\imea arcelor.

Muchiile sunt: U1 = 1,2


U2 = 2,3
U3 = 3,4
U4 = 4,5
U5 = 5,6

2
U2
U1
1 3
U4
U3

5 U5 6
4

Fig. Nr.1 - Exemplu de graf neorientat

Defini\ie: Gradul unui v`rf x, notat d(x) reprezintå numårul muchiilor care
trec prin nodul x (incidente cu x).
Exemplu: în graful din figura nr. 1, gradul v`rfului 2 d(2)=3 (prin v`rful 2
trec 3 muchii çi anume U1,U2 çi U4).
Acest fapt poate duce la redefinirea v`rfurilor, func\ie de gradul acestora:
V`rf izolat: un v`rf care are gradul 0.
V`rf terminal: un v`rf care are gradul 1.

Într-un graf G cum este cel din figura nr. 1 avem mai multe v`rfuri çi fiecare
din acestea au un anume grad. Se pune problema determinårii gradelor totale ale
grafului G sumå care este egalå cu suma gradelor fiecårui v`rf în parte. De aici çi
urmåtoarea teoremå.

Teoremå: Într-un graf G=(X,U) cu n v`rfuri çi m muchii, suma gradelor


tuturor v`rfurilor este egalå cu 2 * numårul muchiilor.
n

 d  x  d  x   d  x     d  x   2  m
i 1
1 2 n

Demonstra\ie: Fiecare muchie are forma XI, Xk unde XI çi Xk sunt v`rfuri
iar i çi k 1,2, . . ., n contribuie cu o unitate la gradul v`rfului i, dar în acelaçi
timp, tot cu o unitate la gradul v`rfului k, deci o muchie cu extremiitå\i oarecare
(exemplu i çi k) då automat douå grade. Cum numårul de muchii într-un graf este
m, rezultå cå suma gradelor este 2*m.

Reprezentarea grafurilor neorientate

Consideråm un graf neorientat G=(X,U) cu m muchii çi n v`rfuri. Forme de


reprezentare a grafurilor neorientate, mai cunoscute sunt:
1. Matricea de adiacen\å
2. Listele vecinilor
3. Vectorul muchiilor

1. Matricea de adiacen\å
Este matricea cu n linii çi n coloane în care elementele ai,j se definesc
astfel:
1, dacå  muchia i j cu ij;
ai,j=
0, în caz contrar

Exemplu:
2
U2
U1
1 3
U4
U3

Fig. nr. 2. - Exemplul 2

Pentru graful din figura nr. 2, matricea de adiacen\å este:

0 1 0 0
 
1 0 1 1
A
0 1 0 1
 
0 1 1 0 

Elementul a2,3 care pe linia 2 çi coloana 3 va fi 1, întruc`t existå în graf


muchia (2,3). Dar aceastå muchie este simetricå cu muchia a(3,2), care este tot 1.
Pe caz general, ai,j = aj,i, oricare ar fi i, j  1,2, . . ., n, cu i  j. De aici
concluzionåm: pentru orice graf neorientat, matricea de adiacen\å a este simetricå
fa\å de diagonala principalå.
Aplica\ii:
Prezentåm în continuare procedura citire_graf, fårå parametrii de
implementare a algoritmului de construire a matricii de adiacen\å prin citirea
muchiilor de la tastaturå: se citesc de la tastaturå m perechi de numere întregi de
forma (x,y), reprezent`nd extremitå\ile celor m muchii ale grafului çi se
construieçte matricea de adiacen\å a cu n linii  n coloane.

Procedura citire_graf:
Procedura citire_graf;
Var i,j,k,x,y:integer;
begin
citeçte numårul de v`rfuri n çi numårul de muchii m
write(‘Numårul de v`rfuri:’);readln(n);
write(‘Numårul de muchii:’);readln(m);
ini\ializeazå cu 0 toatå matricea de adiacen\å
for i:=1 to n do
for j:=1 to n do
ai,j:=0;
citeçte m perechi cu numere întregi de forma (x,y)
for k:=1 to m do
begin
writeln(‘Da\i muchia cu numårul de ordine’, k, ‘:’);
repeat
readln(x,y);
until (x>=1) and (x<=n) and (y>=1) and (y<=n);
pentru fiecare pereche, face 1 elementele ax,y çi ay,x care
identificå muchia (x,y)
ax,y:=1; ay,x:=1;
end;
end;

Aplica\ie:
Afiçarea muchiilor unui graf, pornind de la matricea de adiacen\å.
Matricea de adiacen\å este simetricå fa\å de diagonala principalå,
adic[ muchia(i,j). Deci ai,j=aj,i=1, iar în caz contrar ai,j=aj,i=0. Açadar este
suficient så parcurgem por\iunea de deasupra diagonalei principale, pentru cå aici
gåsim toate valorile de 1 care identifica muchiile destincte.
Så urmårim o matrice cu n linii  n coloane, exemplific`nd pentru n = 4
a1,1 a1,2 a1,3 a1,4
a2,1 a2,2 a2,3 a2,4
a3,1 a3,2 a3,3 a3,4
a4,1 a4,2 a4,3 a4,4

Notåm:
i = indicele de linie
j = indicele de coloanå
elementele de pe diagonala principalå sunt a1,1, a2,2, a3,3, a4,4; în
general, ele sunt de forma ai,j cu i=j, sau altfel spus, ai,i, unde i=1,2, . . . , n;
elementele de deasupra diagonalei sunt:
linia1: a1,2 a1,3 a1,4
linia2: a2,3 a2,4
linia3: a3,4
linia4: nu existå

Observa\ii:
- liniile i care con\in elemente deasupra diagonalei principale, inclusiv, sunt
de la 1 la 3, deci, pa caz general, de la 1 la n-1;
- coloanele j de deasupra diagonalei principale inclusiv, sunt de la 2 la 4
pentru i=1, de la 3 la 4 pentru i=2 ç.a.m.d., Pe caz general j variazå de la
i+1 la n.

Pentru a vizita elementele de deasupra diagonalei principale inclusiv,


parcurgem într-un ciclu liniile i=1,2, . . . , n-1 çi pentru fiecare linie i, parcurgem
într-un alt ciclu coloanele j = i+1, . . ., n aflate deasupra diagonalei principale.
La vizitarea fiecårui element ai,j vom testa dacå acesta este 1. În caz
afirmativ, înseamnå cå existå muchia (i,j), deci vom afiça nodurile extremitå\i i çi j
ale acesteia.
Implementarea algoritmului în procedura afiçare_graf:

Procedura afiçare_graf;
afiçeazå muchiile grafului pornind de la matricea de adiacen\å a
var i,j: integer;
begin
writeln('Muchiile sunt:');
matricea fiind simetricå, se parcurge numai por\iunea de deasupra
diagonalei principale
for i:=1 to n-1 do
for j:=i+1 to n do
if ai,j=1 then writeln (i,' ',j);
afiçeazå muchia (i,j), dacå existå
end;

Aplica\ie:
Citirea matricei de adiacen\å dintr-un fiçier text
Presupunem cå pe primul r`nd al fiçierului se aflå valoarea n (numårul de
linii çi coloane ale matricei, respectiv numårul de v`rfuri al grafului), apoi, pe
fiecare din urmåtoarele m r`nduri se gåsesc elementele unei linii a, a matricei
separate prin spa\ii. Numele fiçierului (care poate con\ine eventual çi calea) va fi
citit de la tastaturå, într-o variabilå nume_fis.
Asignåm descriptorul f fiçierului cu numele nume_fis, apoi deschidem
fiçierul pentru citire. De pe primul r`nd al fiçierului citim valoarea lui n (cu readln
pentru a duce cursorul dupå citire la începutul r`ndului al doilea). Apoi, intr-un
ciclu, contorul i parcurge valorile 1, 2, . . ., n çi la fiecare pas:
- citim linia i a matricei de pe un r`nd din fiçier: într-un alt ciclu parcurgem
coloanele j = 1,2, . . ., n ale liniei i çi citim din fiçier fiecare element ai,j (cu read,
deoarece elementele unei linii a matricei se gasesc pe acelaçi r`nd, separate prin
spa\ii);
- trecem în fiçier la r`ndul urmåtor ( cu readln(f)).

Prezentåm în continuare o procedurå cit_matr_fis care implementeazå


algoritmul descris mai sus.

Procedura cit_matr_fis;
citeçte numårul de noduri çi matricea de adiacen\å din fiçierul text
var: i,j: integer;
nume_fis: string;
begin
write('Da\i numele fiçierului:');readln(nume_fis);
assing(f, nume_fis); reset(f);
readln(f,n);
for i:=1to n do
begin
for j:=1 to n do
read(f, ai,j);
readln(f);
end;
close(f);
end;

Aplica\ie:
Determinarea gradului unui v`rf x pornind de la muchiile de adiacen\å.
Consideråm un graf neorientat G=(X,U) cu n v`rfuri. Gradul unui nod x notat
cu d(x) reprezintå numårul muchiilor care trec prin nodul x, adicå numårul
muchiilor de forma (x,j), cu j  1,2, . . ., n.
Dacå existå muchia (x,j) (cu j  1,2, . . ., n) , atunci în matricea de
adiacen\å avem ax,j=1. Açadar gradul lui x este dat de numårul de 1 de pe linia x
a matricei de adiacen\å.
Scriem o func\ie grad(x:integer): integer; care returneazå gradul v`rfului x.
Vom numåra în variabila gr c`te valori de 1 avem pe linia x a matricei de adiacen\å.
Ini\ializåm cu gradul 0. Parcurgem într-un ciclu for coloanele liniei j, adicå cu j =
1,2, . . ., n çi pentru fiecare coloanå j verificåm dacå ax,j=1; în caz afirmativ, gr
creçte cu o unitate gr:=gr+1;. Func\ia va returna valoarea finalå a lui gr.
Prezentåm în continuare func\ia grad(x).

Function grad(x:integer):integer;
returneazå gradul lui x, adicå numårul muchiilor care trec prin varful x
var j,gr:integer;
begin
gr:=0;
for j:=1 to n do
if ax,j=1 then gr:=gr+1;
grad:=gr;
end;

2. Listele vecinilor

Pentru fiecare nod i (i= cu i= 1,2, . . ., n), formåm lista vecinilor lui i.
Aceasta cuprinde toate nodurile care sunt extremitå\i ale muchiilor ce trec prin
nodul i.

Exemplu:
Fie graful din figura nr. 3:

2
U2
U1
1 3
U4
U3

4
Fig. nr. 3 - Exemplificarea reprezentårii listei vecinilor

Prezentåm matricea de adiacen\å a grafului çi listele vecinilor pentru a face


compara\ie:

coloana 1 2 3 4 nodul Lista vecinilor


0 1 0 0 1 1 2
1 0 1 1 2 Linia 2 1 3 4
A=
0 1 0 1 3 (nodul) 3 2 4
0 1 1 0 4 4 2 3

Fig. nr. 4 - Lista vecinilor

Observåm: pe fircare linie i din listele vecinilor se aflå indicele coloanelor


pe care se gåsesc valori de 1 în linia i a matricei de adiacen\å.

3. Reprezentarea grafului cu un vector de muchii

Fiecare muchie a grafului poate fi privitå ca o inregistrare cu douå


componente çi anume cele douå v`rfuri care constituie extremitå\ile muchiei.
Not`nd aceste extremitå\i cu nod 1 çi nod 2, poate fi defnit tipul de date
TMUCHIE, astfel:

Type TMUCHIE = record


nod1, nod2:integer;
End;

Graful în ansamblul såu este o mul\ime de muchii adicå o mul\ime de


elemente de tipul TMUCHIE. În consecin\å, definim graful ca un vector de muchii,
adicå un vector cu elemente de tipul TMUCHIE:

Var v:array 1..25 of TMUCHIE;


Numårul real de elemente este numårul de muchii m. Astfel, elementele
efectiv folosite ale vectorului vor fi V1, V2, . . ., Vm. Fiecare element Vi, cu
i= 1, 2, . . ., m este de tipul TMUCHIE çi reprezintå o muchie a grafului, av`nd
douå componente:
Vi.nod1, Vi.nod2 - v`rfurile - extremitå\i ale muchiei.

No\iunea de graf par\ial çi subgraf

Defini\ie: Fie graful G=(X,U). Un graf par\ial al lui G este un graf G 1=(X,V),
cu V U. Altfel spus, un subgraf par\ial G1 al lui G este chiar G, sau se ob\ine din
G påstr`nd toate v`rfurile çi suprim`nd unele muchii.

Exemplu:
Pentru graful G= (X,U) de mai construim alåturat graful par\ial ob\ineut prin
eliminarea muchiilor ce trec prin v`rful 4:

Graful G=(X,U) Graful G1=(X,V)


2 2
U2 U2
U1 U1
1 3 1 3
U4
U3

5 U5 6 5 U5 6
4 4
7 7

Fig. nr. 5 - Exemplu de subgraf

Acesta este subgraful din Fig. nr. 5b (G1 = (X,V)), unde X=1,2,3,4,5,6,7,
iar V=U1, U2, U5 ob\inut prin eliminarea muchiilor U3 çi U4 care trec prin nodul
4.
Defini\ie:
Fie graful G= (X,U). Un subgraf al lui G este un graf G 1= (Y,T), unde YX
çi TU, iar V va con\ine numai muchiile care au ambele extremitå\i în Y. Altfel
spus, un subgraf G1 al lui G se ob\ine din G, elimin`nd niçte v`rfuri çi påstr`nd doar
acele muchii care au ambele extremitå\i în mul\imea v`rfurilor råmase.

Exemplu:
Pentru graful G=(X, U) din figura nr. 5a, construim subgraful ob\inut prin
eliminarea v`rfurilor 1 çi 6, aça cum este prezentat în figura nr. 6.
Acesta este G1(Y,T), unde T=U2,U3,U4 çi Y=2,3,4,5,7 (s-au eliminat
nodurile 1 çi 6precum çi muchiile U1 çi U5 care trec prin aceste noduri).

2
U2
3
U4
U3

5
4
7

Fig. nr. 6 - Exemplificare subgraf

Graf complet çi graf bipartit

Defini\ie:
Se numeçte graf complet cu n v`rfuri, notat Kn, un graf G=(X,U), cu
proprietatea cå oricare douå v`rfuri sunt adiacente, adicå:
() x, y  X => () muchia x,yU
Un exemplu de graf complet este prezentat în figura de mai jos:

1 3

4 5

Fig. nr. 7 - Exemplificare graf complet

Teoremå:
n   n  1
Un graf complet cu n v`rfuri, are muchii.
2

Defini\ie:
Se numeçte graf bipartit un graf G=(X,U), cu proprietatea cå existå douå
mul\imi A çi B, incluse în X, astfel înc`t:
- A  B = , A  B = X;
- toate muchiile grafului au o extremitate în A çi alta în B;

Exemplu:
Fie G=(X,U) unde X=1,2,3,4,5,6,7 çi U= U1,U2,U3,U4. Cu mul\imile
A=1,2,3 çi B=4,5,6,7 generåm graful bipartit de mai jos

U1
4
1
U2
5
2 U3 6

3 U4 7
Fig. nr. 8 - Exemplificare graf bipartit

Se observå cå:
A  B = ;
A  B = X;
iar fiecare muchie are o extremitate în A çi o extremitate în B.

Defini\ie:
Se numeçte graf bipartit complet un graf bipartit cu proprietatea cå pentru
orice v`rf x din A çi orice v`rf y din B, existå muchia (x,y), unde A çi B sunt cele
douå submul\imi care parti\ioneazå mul\imea v`rfurilor X.
Un exemplu de graf bipartit complet este ilustrat în figura urmåtoare:

3
1

4
2

Fig. nr. 9 - Exemplificare graf bipartit complet

No\iunea de lan\ çi ciclu

Defini\ie:
Se numeçte lan\ în graful G o succesiune de vårfuri L=(Z 1, Z2, . . ., Zk), unde
Z1, Z2, . . ., Zk X cu proprietatea cå oricare douå vårfuri consecutive sunt
adiacente, adicå existå muchiile  Z1, Z2,  Z2, Z3, . . .,  Zk-1, Zk.U.
V`rfurile Z1 çi Zk se numesc extremitå\ile lan\ului, iar numårul de muchii
care intrå în componen\a sa reprezintå lungimea lan\ului.

Exemplu:
Fie graful din figura urmatoare:

2 5
5

3 4
1

6
7 9

Fig. nr. 10 - Exemplificare lan\uri

În acest graf putem distinge lan\urile: L 1=(1,2,3,5,4,8), L2=(1,2,3,2),


L3=(9,3,5,4,3,2), L4=(6,7,3,5,4,8).
Un lan\ poate fi interpretat ca un traseu care pleacå din v`rful Z 1 çi ajunge în
v`rful Zk, trec`nd prin mai multe v`rfuri çi parcurg`nd mai multe muchii.

Exemplu:
Lan\ul L1=(1,2,3,5,4,8) porneçte din v`rful Z1 çi parcurge muchiile 1,2,
2,3, 3,5, 5,4, 4,8 (în aceastå ordine), ajung`nd astfel în v`rful Z k = 8. Acest
lan\ are lungimea 5, întruc`t include 5 muchii.

Dacå v`rfurile Z1, Z2, . . ., Zk, sunt distincte douå c`te douå, lan\ul se numeçte
elementar. În caz contrar, lan\ul se numeçte neelementar.

Exemplu:
Lan\ul L4 din figura anterioarå este elementar, pentru cå nici un v`rf nu apare
de douå ori. La fel, lan\ul L1. În schimb, lan\urile L2 çi L3 sunt neelementare: în L2
se repetå v`rful 2, iar în L3 se repetå v`rful 3.
Defini\ie:
Se numeçte ciclu într-un graf un lan\ L=(Z 1, Z2, . . ., Zk,) cu proprietatea cå
Z1= Zk çi muchiile  Z1, Z2, Z2, Z3, . . .,  Zk-1, Zk sunt distincte douå c`te douå.

Exemplu:
Fie graful din figura 10. C1=(3,4,5,3,7,6,1,2,3), C2=(1,2,3,7,6,1) çi
C3=(3,5,4,9,3) sunt cicluri. C3 este ciclu deoarece traseul pe care îl descrie porneçte
din v`rful 3 ajung`nd tot în v`rful 3 çi în plus muchiile 3,5, 5,4, 4,9, 9,3 sunt
distincte douå c`te douå (nu apare aceeaçi muchie de douå ori).

Dacå într-un ciclu, toate v`rfurile, cu excep\ia primului çi ultimului sunt


distincte douå c`te douå, atunci ciclul se numeçte elementar. În caz contrar, se
numeçte neelementar.

Exemplu:
Ciclurile C2 çi C3 din exemplul anterior sunt elementare, iar C 1 este
neelementar (în C1 v`rful 3 apare çi ca v`rf intermediar, adicå traseul descris mai
trece odata prin v`rful 3, pe l`ngå faptul cå începe din el çi se întoarce tot în el).

Program principal ce apeleazå procedurile citire_matrice çi secven\a:

Program XI_5;
Uses crt.
Var a:array 1 . . 20, 1 . .20 of integer;
n,i,j,k:integer;
z: array 1 . . 20 of integer;

procedure citire_matrice;
citeçte numårul de muchii çi muchiile de forma (x,y) çi construieçte matricea de
adiacen\å
var i,j,x,y:integer;
begin
write('Numårul de v`rfuri:');readln(n);
for i:=1 to n do ai,i:=0;
for i:=1 to n-1 do
for j:=i+1 to n do
begin
writeln('Existå muchie între ',i,' çi ',j,' ? (1/0) ->');
repeat
readln(ai,j);
until (ai,j=1) or (ai,j=0);
aj,i:= ai,j;
end;
end;

procedure secven\a;
var f:text;
ok:boolean;
begin
assign(f,'lant.txt');reset(f);
k:=0;
while not seekeoln(f) do
begin
k:=k+1;
read(f,zk);
end;
close(f);
for i:=1 to k do write(zi,' ');
writeln;
verificå dacå secven\a e lan\
ok:=true;
for i:=1 to k-1 do
if azi, zi+1=0 then ok:=false;
if ok then write('Lant')
else write('Secven\a nu este lan\');
if ok then
begin
dacå este lan\ elementar
for i:=1 to k-1 do
for j:=i+1 to k do
if zi=zj then ok:=false;
if ok then write('Lant elementar')
else write(' Lant ne-elementar ');
end;
end;

begin
citire_matrice; secven\a;
end.

Program XI_5;
determinarea tuturor lan\urilor într-un graf
Uses crt.
Var n:integer;
a:array 1 . . 20, 1 . .20 of integer;
st: array 1 . . 20 of integer;
f:text;

procedure cit_matr_fis;
citeçte numårul de noduri çi matricea de adiacen\å din fiçierul text
var i,j:integer;
nume_fis:string;
begin
write('Da\i numele fiçierului:');readln(nume_fis);
assign(f,nume_fis);reset(f);
readln(f,n);
for i:=1 to n do
begin
for j:=1 to n do
read(f,ai,j);
readln(f );
end;
close(f);
end;

Procedure initializåri;
ini\ializeazå stiva
var i:integer;
begin
for i:=1 to 25 do sti:=0;
end;

procedure tipar(p:integer);
tipåreçte o solu\ie memoratå în vectorul st
var k:integer;
begin
for k:=1 to p do write(stk:4,'');
writeln;
end;

function valid(p:integer):boolean;
testeazå dacå valoarea puså pe nivelul p a generat o solu\ie validå, return`nd
TRUE sau FALSE
var m,i:integer;
ok:boolean;
begin
ok:=true;
if astp,stp-1=0 then ok:=false;
if ok then
for i:=1 to p-1 do
if stp=sti then ok:=false;
valid:=ok;
end;

procedure bktr(p:integer);
implementeazå algoritmul de backtracking recursiv
var: val:integer;
begin
în variabila val trec pe r`nd toate valorile care ar putea fi incercate pe nivelul
p al stivei
vor val:=1 to n do
begin
stp:=val;
if valid(p) then
if (stp = st1 ) and (p>3) then tipar(p)
else bktr(p+1);
end;
end;

begin
initializari; cit_matr_fis;bktr(1); plecåm de la nivelul 1 pe stivå
end.
Parcurgerea grafurilor neorientate

Prin parcurgerea unui graf se în\elege vizitarea v`rfurilor sale într-o anumitå
ordine, datå de un anumit criteriu. Pentru vizitarea grafurilor neorientate existå
urmåtorii algoritmi:
- algoritmi de parcurgere în lå\ime BF;
- algoritmi de parcurgere în ad`ncime DF;
Pentru în\elegerea acestor no\iuni, am reluat no\iunea de coadå în c`teva
r`nduri:
Coada este o succesiune orientatå de elemente în care adåugarea elementelor
se face la un capå numit capåt de introducere, iar eliminarea elementelor se face pe
la celålalt capåt, numit capåt de extragere. În orice moment putem scoate din coadå
numai elementul aflat la capåtul de extragere. Altfel spus, elementele ies din coadå
în ordinea în care au fost introduse. Datoritå acestor proprietå\i, se vor numi cozi
FIFO (First In First Out) sau în traducereprimul intrat, primul ieçit.
Un exemplu concret de coadå: pentru fiecare zbor de cålåtori o companie
aviaticå întocmeçte o listå a persoanelor care mai solicitå bilete dupå epuizarea
acestora. Lista este organizatå sub forma unei cozi de açteptare ce cuprinde numele
persoanei çi actul de identitate al acesteia. În momentul în care o persoanå doreçte
un bilet este introduså în coadå. Dacå în urma unei renun\åri apare un bilet
disponibil, acesta este atribuit primei persoane ce a fost introduså în coadå.
Beneficiarul lui iese din coadå iar capåtul de extragere avanseazå o pozi\ie.
Coada poate fi implementatå cu ajutorul unui vector. Vom nota:
- pi - pozi\ia capåtului la care se introduc elementele în coadå;
- ps - pozi\ia capåtului pe la care se extrag elementele din coadå;
- max - numårul maxim de elemente din coadå;

Exemplu:
Const max=50;
Var c:array1..max of integer;

Pi Ps

Fig. nr. 11 - Ilustrarea graficå a unei cozi


Vom numi coadå vidå o coadå în care nu avem elemente (p i=ps) çi vom numi
coadå plinå o coadå în care nu se mai pot adåuga elemente. (ps=max).
Adåugarea çi extragerea elementelor poate fi descriså astfel:
a) adåugarea unui element înseamnå creçterea lui pi cu o unitate çi memorarea
elementului pe noua pozi\ie pi (elementul cpi). Se poate face numai în cazul în
care coada nu este plinå (ps < max);
a) extragerea unui element înseamnå creçterea lui ps cu o unitate. Poate avea
loc în cazul în care coada nu este vidå (pi=ps);
Så urmårim evolu\ia unei cozi în care introducem si din care extragem aleator
c`teva elemente:
Ps Pi
- în coada ini\ial vidå introducem
5
elementul cu valoarea 5;
Ps=1 Pi=1
- pe la acelaçi capåt introducem
5 7 elementul cu valoarea 7;
Ps=1 Pi=3
- adåugåm çi elementul -4;
5 7 -4

Ps=2 Pi=3
- extragem un element din coadå, cel
7 -4 introdus primul, adicå 5;

Fig. nr. 12 - Exemplu de func\ionare a unei cozi

Algoritm de parcurgere în lå\ime BF

I. Metoda de parcurgere Breadth First (BF) în lå\ime.


Se porneçte de la un v`rf de start care se viziteazå, apoi se viziteazå to\i
vecinii lui. Pentru fiecare din aceste v`rfuri se viziteazå vecinii care nu au fost încå
vizita\i. Pentru noile v`rfuri se precizeazå la fel: se viziteazå vecinii acestora care
nu au fost încå vizita\i.
Procedeul continuå p`nå c`nd s-au vizitat toate v`rfurile.

Exemplu:
Fie graful G=(X,U) din figura urmåtoare:

5
2

3 4 7

Fig. nr. 13 - Exemplu pentru parcurgerea BF

Presupunem cå v`rful de start este 1.


Paçii parcurgerii sunt:
1. vizitåm mai înt`i v`rful de start;
2. vizitåm vecinii lui 1, adicå 2, 5 çi 6
3. pentru fiecare din vecinii lui 1 vizitåm vecinii nevizita\i, adicå:
- vecinii lui 2 sunt 1, 3 çi 4, dar nevizita\i sunt doar 3, 4;
- vecinii lui 5 sunt 1, 2 çi 7, dar nevizitat este doar 7;
- vecinii lui 6 sunt 1 çi 7 dar ambii sunt vizita\i;
4. Am vizitat p`nå acum vecinii v`rfurilor 1, 2, 5, 6. Mai trebuie vizita\i vecinii
noilor v`rfuri vizitate la pasul anterior çi anume vecinii v`rfurilor 3, 4 çi 7.
Observåm înså cå aceste v`rfuri nu mai au vecini nevizita\i, deci parcurgerea se
încheie.
pi
Ordinea vizitårii v`rfurilor în parcurgerea BF este 1, 2, 5, 6, 3, 4, 7.
p
Vom s folosi o coadå implementatå cu ajutorul unui vector c. Capetele de
introducere çi extragere vor fi identificate cu - ajutorul
introducem
(prinînpozi\iile)
coadå pv`rful de
i çi respectiv
1
ps. Introducem mai înt`i nodul de start înstart 1; apoi în mod repetat p`nå la
coadå,
vizitarea tuturor
ps nodurilor:
pi
- extragem extragem - extragem
din coadå v`rful aflat v`rful
la capåtul 1 çi introducem
de extragere çi îl vizitåm;
- introducem
1 2 5 în coadå
6 vecinii såi nevizita\i (neintroduçi)
pe la capåtul de introducere vecinii nevizita\i ai v`rfului
extras; încå 2, 5, 6;
ps pi
Evolu\ia cozii pentru graful din figura- nr. extragem
13 este 2urmåtoarea:
çi introducem vecinii
1 2 5 6 3 4 såi nevizita\i 3 çi 4;

ps pi
- extragem 5 çi introducem unicul
1 2 5 6 3 4 7 såu vecin nevizitat, 7;
Fig. nr. 14 - Ilustarea evolu\iei cozii pentru exemplul considerat

În continuare se vor extrage pe r`nd v`rfurile 6, 3, 4, 7. Niciunul dintre aceste


v`rfuri nu mai are vecini nevizita\i, deci nu se va mai introduce nimic în coadå. În
concluzie, capåtul de introducere pi nu se mai modificå.

Concluzii: Dupå fiecare extragere a unui v`rf, capåtul de extragere ps se va


muta la pozi\ia urmatoare celei de pe care s-a fåcut extragerea. De exemplu, dupå
ce am extras v`rful 5 de pe pozi\ia 3, p s s-a mutat la pozi\ia urmåtoare lui 3, adicå 4.
Aça se face cå dupå extragerea ultimului v`rf de pe pozi\ia 7 care este 7 capåtul de
extragere (punct de scoatere) ps va ocupa (trece) pozi\ia 8, deci se va muta dincolo
de capåtul de introducere pi care råm`ne 7, adicå ciclul descris mai sus se opreçte.
Deci ciclul ai cårui paçi au fost descriçi mai sus se executå c`t timp pi<=ps.
pi ps
1 2 3 4 5 6 7 8
1 2 5 6 3 4 7

Fig. nr. 15 - Reprezentarea graficå a cozii parcurse

Implementarea algoritmilor

Notåm cu n numårul de noduri din graf. Este necesar ca elementele matricei


de adiacen\å a cu n linii çi n coloane så fie cunoscute.
Mai avem nevoie de un vector VIZ cu n elemente în care elementele VIZk
k=(1, 2, . . ., n) au semnifica\ia:

1, dacå v`rful k a fost vizitat


VIZk=
0, în caz contrar

Utilizarea vectorului VIZk.


Mai înt`i îl ini\ializåm cu 0.
For k:= 1 to 20 do vizk:=0;

C`nd introducem un v`rf oarecare în coadå, marcåm faptul cå urmeazå a fi


vizitat, fåc`nd atribuirea v<numårul v`rfului>:=0.
La fiecare pas, dupå ce extragem din coadå v`rful aflat în capåtul de
extragere, trebuie så introducem pe la celålalt capåt vecinii nevizita\i ai v`rfului
extras. Pentru fiecare din aceçti vecini vom verifica cu ajutorul vectorului viz daca
a fost sau nu vizitat.

Exemplu:
În graful din figura nr. 13, ce se înt`mplå la extragerea v`rfului 5? Vecinii lui
5 sunt 1, 2 çi 7. Dar v`rfurile 1 çi 2 au fost vizitate deja, deci parcurg`nd vectorul
viz vom gåsi:
viz1=1
viz2=1

În schimb v`rful 7 nu a fost vizitat, deci vom gåsi viz7=0, motiv pentru care
îl introducem în coadå. Facem apoi viz7=1 marc`nnd vizitarea v`rfului 7 cu
scoaterea lui din coadå çi asigur`ndu-ne prin procedeul de mai sus cå nu va mai fi
introdus încå o datå în coadå.
Analog cu ini\ializarea vectorului viz trebuie så se ini\ializeze çi coada c.
For k:=1 to 20 do ck:=0;
Evident, ini\ial pi:=1 çi ps:=1. Notåm nodul de start cu prim çi îl introducem
în coadåpe pozi\ia datå de capåtul de introducere pi(cpi:=prim), marc`nd totodatå
vizitarea lui (vizprim:=1).
C`t timp mai sunt elemente în coadå (while ps<=pi):
- extragem din coadå v`rful aflat în capåtul de extragere p s çi-l memoråm
într-o variabilå z:z:=cps. Evident, la primul pas z va fi c1, adicå nodul de start
prim;
- cåutåm vecinii nevizita\i ai lui z çi îi introducem în coadå.
Vecinii lui z îi gåsim pe linia z a matricii de adiacen\å. Acelea dintre
elementele az,1, az,2 , . . . , az,n care sunt 1 ne indicå vecinii lui z. Mai precis,
dacå az,k este 1 atunci v`rful k este vecin al lui z, pentru k=1, 2, . . . , n.
Dar, dupå ce am gåsit un vecin k al lui z acela trebuie så mai fie çi nevizitat.
Cine ne spune dacå acest v`rf k a fost vizitat? Evident, elementul vizk al
vectorului viz (cu n elemente), element care trebuie så aibå valoarea 0. Açadar,
într-un ciclu for, contorul k ia pe r`nd valorile 1, 2, . . ., n, parcurg`ndu-se astfel
numerele de ordine ale tuturor v`rfurilor.
La fiecare pas, dacå v`rful k este vecin nevizitat al lui z (az,k=0 çi
vizk=0), atunci:
- creçte cu o unitate pozi\ia capåtului de introducere (pi:=pi+1);
- introducem v`rful k in coada c pe la noul capåt de introducere;
- marcåm vizitarea v`rfului k prin atribuirea vizk=0;

Fiecare pas al ciclului se încheie cu creçterea cu o unitate a capåtului de


extragere (ps=ps+1), necesarå deoarece tocmai am extras un element, în spe\å v`rful
memorat in z.

Observa\ie:
V`rfurile nu sunt afiçate deoarece la sf`rçitul algoritmului toate v`rfurile se
gåsesc în coada c exact în ordinea în care au fost vizitate. Extragerea unui v`rf din
coadå nu înseamnå çtergerea (eliminarea) lui din coada respectivå. Extragerea se
realizeazå numai prin deplasarea cåtre dreapta a capåtului de extragere ps (mårire
lui, de fapt, cu o unitate). Deci, pentru a tipåri v`rfurile în ordinea vizitårii lor
afiçåm intr-un ciclu con\inutul vectorului-coadå c.
Mai apare o întrebare: c`te elemente sunt într-o coadå? (toate nodurile
grafului, mai pu\ine?)
Pentru a råspunde, consideråm graful din figura urmåtoare:

1 3

6 4
5
Fig. nr. 15 - Exemplu pentru calcularea elementelor dintr-o coadå

Parcurg`nd graful cu algoritmul BF, lu`nd v`rful 1 ca v`rf de start, observåm


cå sunt vizitate çi implicit puse în coadå numai v`rfurile 1, 2, 3 çi 4 (în aceastå
ordine).
Dacå luåm v`rful 5, de exemplu, ca v`rf de start, vom reuçi så vizitåm numai
v`rfurile 5 çi 6. Grafurile de acest gen, caracterizate prin faptul cå la o parcurgere
nu pot fi vizitate toate v`rfurile, fac obiectul capitolului Conexitate, capitol
prezentat în lucrarea de fa\å.
Revenind la problema de mai sus çi anume numårul de v`rfuri ce vor fi puse
în coadå, este evident cå vor fi at`tea c`te vor fi introduse p`nå la finele parcurgerii.
La fiecare introducere, capåtul de introducere pi creçte cu o unitate (plec`nd de la
valoarea 1), aça cå valoarea finalå a lui pi va reprezenta numårul de noduri puse în
coadå, respectiv vizitate.
În acest moment, afiçarea nodurilor vizitate nu mai este o problemå: într-un
ciclu for contorul k parcurge pozi\iile elementelor din coadå, de la 1 la p i çi la
fiecare pas se afçeazå elementul ck:
For k:=1 to pi do write(ck:3);

Prezentarea unei secven\e de program care realizeazå parcurgerea cu


algoritmul BF:

For k:=1 to 20 do ck:=0;


For k:=1 to 20 do vizk:=0;
Pi:=1; ps:=1;cpi:=prim;vizprim:=1;
While ps<=pi do
Begin
z:=cps;
For k:=1 to n do
If (az,k=1) and (vizk=0) then
Begin
Pi:=pi+1;cpi:=k; vizk:=1;
End;
Ps:=ps+1;
End;
For k:=1 to pi do write(ck:3);

Pseudocodul algorritmului BF:

Fie G un graf neorientat cu k noduri.


Procedure BF(k)
1. vizitk=1
2. c <- k
3. while (c   ) do
1. i <- c
2. for each nod j vecin cu i çi încå nevizat do
1. vizitj=1;
2. c <- j;
3. endfor
4. endwhile

II. Metoda de parcurgere Depth First DF "în ad`ncime"


Parcurgerea unui graf în acest mod este o metodå specificå metodei de
rezolvare backtracking. Pentru rezolvarea problemei se foloseçte un vector
VIZITAT definit ca la metoda BF, înså în locul cozii se va folosi o stivå (simulatå
în alocarea staticå printr-un vector V). Astfel, în orice moment existå posibilitatea
de a ajunge de la v`rful curent la primul dintre vecinii såi nevizita\i încå, acesta
fiind plasat în v`rful stivei. Cu acest v`rf, se continuå în acelaçi mod.
În vectorul URM se determinå la fiecare pas urmåtorul nod ce va fi vizitat
dupå nodul k (c`nd acesta existå). Pentru a-l determina, se parcurge linia k din
matricea de adiacen\å 1 asociatå grafului, încep`nd cu urmåtorul element, p`nå se
gåseçte un vecin j al lui k, nevizitat încå.
Dacå este gåsit, se încarcå în v`rful stivei çi se måreçte corespunzåtor
pointerul de stivå p. Dacå sunt mai mul\i vecini, se alege acela care are cel mai mic
numår de ordine, pentru ca no\iunea de rådåcinå så aibå sens.
Dacå nu se poate determina un astfel de v`rf, se coboarå în stivå (pointerul de
stivå p se micçoreazå cu 1) încerc`nd så aplicåm procedeul urmåtorului element din
stivå.
Folosind o structurå de tip stivå, prelucrårile unui v`rf k aflat la un capåt al
stivei (v`rful stivei), constå în introducerea în acelaçi capåt al ei a tuturor v`rfurilor
j vecine cu k, nevizitate încå. Evident, pentru început, k este egal cu v`rful indicat
ini\ial i.
Algoritmul constå în urmåtorii paçi:
Pas 1. Se adaugå v`rful k în stivå çi se afiçeazå;
Pas 2. Se analizeazå v`rful k:
Pas. 2.1. Se cautå primul dintre vecinii nevizita\i cu numår > k;
Pas 2.1.1. dacå existå (fie acesta j) se adaugå în stivå v`rful j çi se afiçeazå
Pas 2.1.2. dacå nu existå se coboarå în stivå; con\inutul
corespunzåtor al stivei fie j
Pas 2.2. v`rful j devine v`rful ce trebuie analizat (v`rf k)
Pas 3. C`t timp stiva este nevidå, se executå pas 2

Exemplu:

2
3
4

5
6

7
8

Fig. nr. 16 - Exemplu pentru calcularea elementelor dintr-o coadå

Se doreçte parcurgerea sa încep`nd cu v`rful 1. În figura 16 s-a marcat cu


linie punctatå traseul de vizitare a v`rfurilor în ad`ncime.
Pentru aceasta se executå paçii:

Succesiunea paçilor Con\inut stivå


Se adaugå în stivå v`rful 1 (v`rful ini\ial) 1
Se afiçeazå v`rful 1
Se analizeazå v`rful 1 (ca prim element al stivei)
Se determinå primul dintre vecinii såi: 2
Se adaugå în stivå v`rful 2 çi se afiçeazå 1,2
Se analizeazå v`rful 2 (ca element curent al stivei)
Se determinå primul dintre vecinii såi: 5
Se adaugå în stivå v`rful 5 çi se afiçeazå 1,2,5
Se analizeazå v`rful 5 (ca element curent al stivei)
Se determinå primul dintre vecinii såi: 7
Se adaugå în stivå v`rful 7 çi se afiçeazå 1, 2, 5, 7
Se analizeazå v`rful 7 (ca element curent al stivei) 1, 2, 5
Se cautå primul dintre vecinii såi nevizita\i cu numår >7
Nu existå, se coboarå în stivå.
Se analizeazå v`rful 5 (ca element curent al stivei) 1, 2
Se cautå primul dintre vecinii såi nevizita\i cu numår >5
Nu existå; se coboarå în stivå
Se analizeazå v`rful 2 (ca element curent al stivei) 1
Se cautå primul dintre vecinii såi nevizita\i cu numår >2
Nu existå; se coboarå în stivå
Se analizeazå v`rful 1 (ca element curent al stivei) 1,3
Se cautå primul dintre vecinii såi nevizita\i cu numår >1
Se adaugå în stivå v`rful 3 çi se afiçeazå
Se analizeazå v`rful 3 (ca element curent al stivei) 1, 3, 6
Se cautå primul dintre vecinii såi nevizita\i cu numår >3
Se adaugå în stivå v`rful 6 çi se afiçeazå
Se analizeazå v`rful 6 (ca element curent al stivei) 1, 3, 6, 8
Se cautå primul dintre vecinii såi nevizita\i cu numår >6
Se adaugå în stivå v`rful 8 çi se afiçeazå
Se analizeazå v`rful 8 (ca element curent al stivei) 1, 3, 6
Se cautå primul dintre vecinii såi nevizita\i cu numår >8
Nu existå; se coboarå în stivå
Se analizeazå v`rful 6 (ca element curent al stivei) 1, 3
Se cautå primul dintre vecinii såi nevizita\i cu numår >6
Nu existå; se coboarå în stivå
Se analizeazå v`rful 3 (ca element curent al stivei) 1
Se cautå primul dintre vecinii såi nevizita\i cu numår >3
Nu existå; se coboarå în stivå
Se analizeazå v`rful 1 (ca element curent al stivei) 1, 4
Se cautå primul dintre vecinii såi nevizita\i cu numår >1
Se adaugå în stivå v`rful 4 çi se afiçeazå
Se analizeazå v`rful 4 (ca element curent al stivei) 1
Se cautå primul dintre vecinii såi nevizita\i cu numår >4
Nu existå; se coboarå în stivå
Se analizeazå v`rful 1 (ca element curent al stivei) -
Se cautå primul dintre vecinii såi nevizita\i cu numår >1
Nu existå; se coboarå în stivå

Succesiunea de v`rfuri afiçate 1, 2, 5, 7, 3, 6, 8, 4 indicå succesiunea de


v`rfuri rezultatå din parcurgerea acestui graf folosind metoda DF.

Programul Pascal corespunzåtor este:

Program parcurgere_df;
Uses crt;
Var vizitat:array1..20 of 0..1;
A:array1..20,1..20 of integer;
V, urm:array1..20 of integer;
N, m, p, i, j, k, x1, x2:integer;
urm - re\ine dacå existå nodul ce va fi vizitat dupå nodul j
toate celelalte c`mpuri au aceeaçi semnifica\ie

procedure init;
ini\ializare matrice adiacentå çi a vectorului vizitat
begin
for i:=1 to n do
begin
vizitati:=0;
for j:=1 to n do ai,j:=0;
end;
end;

procedure complet;
completare matrice de adiacen\å
begin
for i:=1 to n do
begin
write('Extremitå\ile muchiei ',i,':');read(x1);
write('Extremitå\ile muchiei ',i,':');read(x2);
ax1,x2:=1; ax2,x1:=1;
end;
end;

Procedure prelucrare;
Begin
J:=vp; se extrage primul v`rf din stivå
K:=urmj+1;
determinå primul dintre vecinii k ai lui j nevizita\i încå
while (k<=n) and ((aj,k=0) or ((aj,k=1) and (vizitatk=1))) do k:=k+1;
urmj:=k;
if k=n+1 then p:=p+1 dacå nu existå un asemenea k se coboarå în stivå
else
begin
vizitat k=1 se marcheazå vårful k
p:=p+1; se trece pe nivelul urmåtor în stivå
vp=k; se memoreazå v`rful k
write(k,' '); se afiçeazå v`rful k
end;
end;

program principal
begin
clrscr;
write('Introduceti numårul de v`rfuri n:');readln(n); init;
write('Introduceti numårul de muchii m:');readln(m); complet;
write('V`rful de plecare:');
readln(i); introducere v`rf de plecare
prelucrarea primului v`rf
v1:=i; introduce v`f i în stiva v
p:=1; referire la primul element al stivei
vizitati:=1; se marcheazå v`rful i ca fiind vizitat
writeln('Plec`nd din v`rful ',i,',');
writeln('parcurg`nd graful prin metoda DF');
writeln('succesiunea v`rfurilor este:');
write(' ',i,',');
while p>=1 do prelucrare; c`t timp stiva nu este vidå, executå prelucrare
end.
Conexitate în grafuri neorientate
Fie graful din figura de mai jos:

5
2

3 4 7

Fig. nr. 17 - Exemplu pentru ilustrarea conexitå\ii

Parcurg`nd graful din figura nr. 17 cu algoritmul de parcurgere în lå\ime BF,


am ob\inut urmåtoarea succesiune a v`rfurilor vizitate: 1, 2, 5, 6, 3, 4, 7.
Proprietatea care s-a eviden\iat în urma parcurgerii grafului prin metoda BF a
fost cå au fost vizitate toate v`rfurile. De aici rezultå urmåtoarea consecin\å:
Lu`nd în considerare douå v`rfuri putem gåsi cel pu\in un traseu care
porneçte dintr-un v`rf çi ajunge în celålalt.
Un astfel de traseu va trece prin alte v`rfuri intermediare, parcurg`nd niçte
muchii.

Exemplu:
Între v`rfurile 1 çi 5 din figura nr. 17, putem gåsi urmåtoarele trasee:
- (1, 2, 5) - parcurge muchiile 1, 2, 2, 5;
- (1, 6, 7, 5) - parcurge muchiile 1, 6, 6, 7, 7, 5;
- (1, 5) - parcurge muchia 1, 5 çi este çi ea tot un traseu;

Aceste trasee sunt lan\uri. În concluzie, lu`nd oricare douå v`rfuri, ele pot fi
legate printr-un lan\. Aceastå proprietate conferå grafului din figura nr 17 statutul
de graf conex.

Defini\ie:
Un graf G este conex dacå oricare ar fi douå v`rfuri ale sale, existå un lan\
care le leagå.
Dar nu toate grafurile sunt conexe. Vom da un exemplu de graf în care,
apel`nd la algoritmul de parcurgere BF nu putem vizita toate nodurile, indiferent de
nodul de start. Un astfel de graf este cel din figura nr. 18.

1
3
6 7

4 5

8 9

Fig. nr. 18 - Exemplu de grafic neconex

Dacå luåm v`rful 1 ca v`rf de start, atunci vecinii lui 1 sunt 2 çi 4, vecin
nevizitat al lui 3 este doar 5, deci ordinea vizitårii v`rfurilor este 1, 2, 4, 3, 5. Au
råmas nevizitate v`rfurile 6, 7, 8, 9.
Similar, dacå luåm de exemplu v`rful 6 ca v`rf de start, vom vizita numai
v`rfurile 6, 7, 8, 9, råm`n`nd nevizitate v`rfurile 1, 2, 3, 4, 5.
Urmare faptului cå la o parcurgere nu putem vizita toate v`rfurile, consecin\a
este clarå: nu oricare douå noduri pot fi legate printr-un lan\. De aici rezultå cå
graful din figura 6 nu este conex. În schimb, dupå cum vom vedea în continuare,
putem desprinde din el douå por\iuni, care, fiecare luatå separat, reprezintå un graf
conex.
Vom spune despre graful din figura nr. 18 cå are douå componente conexe.

Defini\ie:
Se numeçte componentå conexå a grafului G=(X,U) un subgraf G1=(X1,U1)
al lui G, conex, cu proprietatea cå nu existå nici un lan\ care så lege un v`rf din X 1
cu un v`rf din X-X1.

Exemplu:
Componentele conexe ale grafului din figura nr. 18, sunt:
- G1=(X1,U1) cu X1=1, 2, 3, 4, 5 çi U1=(1, 2), (2, 3), (3, 5), (5, 4);
- G2=(X2,U2) cu X2=6, 7, 8, 9 çi U2=(6, 7), (7, 9), (9, 8), (8, 6);
G1=(X1,U1) este componenta conexå a lui G.

Demonstra\ie:
G1 este subgraf al lui G, ob\in`ndu-se din G prin eliminarea nodurilor 6, 7, 8,
9 çi påstr`nd doar muchiile care au ambele extremitå\i în mul\imea muchiilor
råmase.
G1 este conex deoarece oricare ar fi douå noduri ale sale existå un lan\ care le
leagå.
Pentru X1=1, 2, 3, 4, 5, avem X=X1=6, 7, 8, 9. Se observå cå nu existå
nici un lan\ care så lege un v`rf din X1 cu un v`rf din X-X1.
Un astfel de lan\ ar trebui sa plece dintr-un v`rf aflat în X 1, så treacå prin mai
multe noduri pe un traseu format din muchii çi så ajungå într-un v`rf aflat în X=X 1,
dar nu existå muchii care så aibå o extremitate în X1 çi alta în X-X1. Deci practic nu
se poate trece din X1 în X-X1. Demonstra\ia este similarå pentru G2=(X2,U2).

Din cele aråtate mai sus (defini\ii, exemple), se concluzioneazå:


- dacå numårul componentelor conexe dintr-un graf este mai mare ca 1,
atunci graful nu este conex;
- un graf conex are o singurå componentå conexå, care cuprinde toate
nodurile sale.

Aplica\ii:

Verificarea conexitå\ii unui graf


Se dåmatricea de adiacen\å a unui graf cu n v`rfuri çi se cere så se verifice
dacå este conex sau nu:
Pentru verificarea conexitå\ii grafului se pleacå de la observa\ia urmåtoare:
un graf conex are o singurå componentå conexå care cuprinde toate v`rfurile
grafului. Altfel spus, dacå în urma parcurgerii grafului (ex algoritm BF) s-au vizitat
toate v`rfurile, indiferent care a fost v`rful de start, atunci graful este conex.

În programul principal se apeleazå func\ia conex, afiç`ndu-se valoarea


returnatå:
Program conex_;
Var m, n, pi, ps, prim, p, nrc: integer;
A:array1..20, 1..20 of integer;
C, viz:array1..20 of integer;

Procedure citire_graf;
citeçte numårul de muchii çi muchiile de forma (x, y) çi construiçte matricea de
adiacen\å
begin
...
end;

procedure afiçare_matrice;
afiçeazå matricea de adiacen\å
begin
...
end;

function nevizitat:integer;
parcurge tabloul viz; returneazå primul nod nevizitat, sau -1 daca nu mai sunt
noduri nevizitate
var prim_nev, j:integer;
begin
prim_nev:= -1;
j:=1;
while (j<=n) and (prim_nev=-1) do
begin
if vizj=0 then prim_nev=j;
j:=j+1;
end;
nevizitat:=prim_nev;
end;

functin conex:boolean;
verificå dacå graful este conex, return`nd valoarea true sau false
var k, pi, ps, z:integer;
begin
face o parcurgere a grafului cu algoritmul BF, plec`nd de la nodul
desemnat prim
write('Da\i v`rful de plecare:');
readln(prim);
for k:=1 to 20 do ck:=0
for viz:=1 to 20 do vizp:=0
pi:=1; ps:=1; c1:=prim; vizprim:=1;
while ps <=p do
begin
z:=cps;
for k:=1 to n do
if (az,k=1) and (viz(k)=0) then begin
pi:=pi+1; cpi:=k; vizk:=1;
end;
for k:=1 to pi do write(ck:3);
if nevizitat = -1 then connex:=true
else conex:=false;
end;

Begin
Writeln('Afiçåm componente conexe:');
Citire_graf;
Afiçare_matrice;
Write(n, conex);
End.

Descompunerea unui graf în componente conexe:

Se då matricea de adiacen\å a unui graf neorientat cu n v`rfuri çi se cere så se


afiçeze toate componentele conexe precum çi numårul acestora.

Programul principal:
- se apeleazå procedura citire_graf, pentru a citi muchiile çi a completa
matricea de adiacen\å;
- ini\ializarea în ciclcu a vectorului viz cu 0;
- citirea numårului nodului de start în variabila prim.
- se ini\ializeazå cu 0 numårul componentelor conexe nc;
- repetå
- nc:=nc+1;
- parcurgere_BF(prim) parcurgere graf în lå\ime
- trebuie våzut dacå în urma parcurgerii au råmas v`rfuri nevizitate.
Pentru aceasta memoråm în variabila prim numårul primului nod care
nu a fost vizitat, returnat de cåtre func\ia nevizitat: prim:=nevizitat;
- p`nå c`nd prim = -1
write('Da\i v`rful de plecare'); readln(prim);
nc:=0;
repeat
nc:=nc+1
parcurgere_BF(prim);
writeln;
prim:=nevizitat;
until prim = -1;

Programul complet:

Program comp_conexe;
Var m, n, pi, ps, prim, pc, nc:integer;
A:array1..20, 1..20 of integer;
C, viz:array1..20 of integer;

Procedure citire_matrice;
Var i,j,k,x,y:integer;
Begin
Write('Numårul de v`rfuri:');readln(n);
Write('Numårul de muchii:');readln(m);
ini\ializeazå cu 0 toatå matricea de adiacen\å
for i:= 1 to n do
for j:=1 to n do ai, j:=0;
citeçte m perechi de numere întregi de forma (x, y); pentru fiecare pereche
actualizeazå cu 1 elementele ax, y çi ay,x care identificå muchia x, y
for k:=1 to m do
begin
write('Da\i muchia cu numårul de ordine',k,':');
repeat
readln(x,y);
until (x>=1) and (x<=n) and (y>=1) and (y<=n);
ax,y:=1;ay,x:=n;
end;
end;

funtion nevizitat:integer;
parcurge tabloul viz; returneazå primul nod nevizitat, sau -1 dacå nu mai sunt
noduri nevizitate
var prim_nev, j:integer;
begin
prim_nev:=-1;
j:=1;
while (j<=1) and (prim_nev=-1) do
begin
if vizj=0 then prim_nev:=j;
j:=j+1;
end;
nevizitat:=prim_nev;
end;

procedure parcurgere_BF(prim:integer);
face o parcurgere a grafului cu BF plec`nd de la nodul de start prim
var k, pi, ps, z:integer;
begin
for k:=1 to 20 do ck:=0;
pi:=1; ps:=1;
c1:=prim; vizprim:=1;
while ps<=pi do
begin
z:=cps;
for k:=1 to n do
if (az,k=1) and (vizk=0) then
begin
pi:=pi+1;cpi:=k; vizk:=1;
end;
ps:=ps+1;
end;
for k:=1 to pi do write(ck:3);
end;

begin
writeln('Afiçåm componentele conexe:');
citire_matrice;
for p:=1 to 20 do vizp:=0;
write('Da\i v`rful de plecare:');readln(prim);
nc:=0;
repeat
nc:=nc+1;
parcurgere_BF(prim);writeln;
prim:=nevizitat;
until prim=-1;
end.

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