Documente Academic
Documente Profesional
Documente Cultură
Scurt istoric
No\iuni de bazå
Grafuri Neorientate
Exemplu:
2
U2
U1
1 3
U4
U3
5 U5 6
4
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å.
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.
1. Matricea de adiacen\å
Este matricea cu n linii çi n coloane în care elementele ai,j se definesc
astfel:
1, dacå muchia i j cu ij;
ai,j=
0, în caz contrar
Exemplu:
2
U2
U1
1 3
U4
U3
0 1 0 0
1 0 1 1
A
0 1 0 1
0 1 1 0
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
ai,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 ax,y çi ay,x care
identificå muchia (x,y)
ax,y:=1; ay,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 ai,j=aj,i=1, iar în caz contrar ai,j=aj,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
a1,1 a1,2 a1,3 a1,4
a2,1 a2,2 a2,3 a2,4
a3,1 a3,2 a3,3 a3,4
a4,1 a4,2 a4,3 a4,4
Notåm:
i = indicele de linie
j = indicele de coloanå
elementele de pe diagonala principalå sunt a1,1, a2,2, a3,3, a4,4; în
general, ele sunt de forma ai,j cu i=j, sau altfel spus, ai,i, unde i=1,2, . . . , n;
elementele de deasupra diagonalei sunt:
linia1: a1,2 a1,3 a1,4
linia2: a2,3 a2,4
linia3: a3,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.
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 ai,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 ai,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)).
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, ai,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 ax,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å ax,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 ax,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
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:
5 U5 6 5 U5 6
4 4
7 7
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 YX
çi TU, 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
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,yU
Un exemplu de graf complet este prezentat în figura de mai jos:
1 3
4 5
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
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
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).
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 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 ai,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(ai,j);
until (ai,j=1) or (ai,j=0);
aj,i:= ai,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,zk);
end;
close(f);
for i:=1 to k do write(zi,' ');
writeln;
verificå dacå secven\a e lan\
ok:=true;
for i:=1 to k-1 do
if azi, zi+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 zi=zj 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,ai,j);
readln(f );
end;
close(f);
end;
Procedure initializåri;
ini\ializeazå stiva
var i:integer;
begin
for i:=1 to 25 do sti:=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(stk: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 astp,stp-1=0 then ok:=false;
if ok then
for i:=1 to p-1 do
if stp=sti 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
stp:=val;
if valid(p) then
if (stp = st1 ) 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:array1..max of integer;
Pi Ps
Ps=2 Pi=3
- extragem un element din coadå, cel
7 -4 introdus primul, adicå 5;
Exemplu:
Fie graful G=(X,U) din figura urmåtoare:
5
2
3 4 7
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
Implementarea algoritmilor
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:
viz1=1
viz2=1
În schimb v`rful 7 nu a fost vizitat, deci vom gåsi viz7=0, motiv pentru care
îl introducem în coadå. Facem apoi viz7=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 ck:=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(cpi:=prim), marc`nd totodatå
vizitarea lui (vizprim:=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:=cps. Evident, la primul pas z va fi c1, 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 az,1, az,2 , . . . , az,n care sunt 1 ne indicå vecinii lui z. Mai precis,
dacå az,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 vizk 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 (az,k=0 çi
vizk=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 vizk=0;
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å
Exemplu:
2
3
4
5
6
7
8
Program parcurgere_df;
Uses crt;
Var vizitat:array1..20 of 0..1;
A:array1..20,1..20 of integer;
V, urm:array1..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
vizitati:=0;
for j:=1 to n do ai,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);
ax1,x2:=1; ax2,x1:=1;
end;
end;
Procedure prelucrare;
Begin
J:=vp; se extrage primul v`rf din stivå
K:=urmj+1;
determinå primul dintre vecinii k ai lui j nevizita\i încå
while (k<=n) and ((aj,k=0) or ((aj,k=1) and (vizitatk=1))) do k:=k+1;
urmj:=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å
vp=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
v1:=i; introduce v`f i în stiva v
p:=1; referire la primul element al stivei
vizitati:=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
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
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).
Aplica\ii:
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 vizj=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 ck:=0
for viz:=1 to 20 do vizp:=0
pi:=1; ps:=1; c1:=prim; vizprim:=1;
while ps <=p do
begin
z:=cps;
for k:=1 to n do
if (az,k=1) and (viz(k)=0) then begin
pi:=pi+1; cpi:=k; vizk:=1;
end;
for k:=1 to pi do write(ck: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.
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:array1..20, 1..20 of integer;
C, viz:array1..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 ai, j:=0;
citeçte m perechi de numere întregi de forma (x, y); pentru fiecare pereche
actualizeazå cu 1 elementele ax, y çi ay,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);
ax,y:=1;ay,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 vizj=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 ck:=0;
pi:=1; ps:=1;
c1:=prim; vizprim:=1;
while ps<=pi do
begin
z:=cps;
for k:=1 to n do
if (az,k=1) and (vizk=0) then
begin
pi:=pi+1;cpi:=k; vizk:=1;
end;
ps:=ps+1;
end;
for k:=1 to pi do write(ck:3);
end;
begin
writeln('Afiçåm componentele conexe:');
citire_matrice;
for p:=1 to 20 do vizp:=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.