Sunteți pe pagina 1din 18

I.

INTRODUCERE ÎN TEORIA GRAFURILOR

1.1. Grafuri neorientate

Definitie. Fie X o mulțime finită si nevidă si U ⊂{{x, y}| x, y ∈ X}. Numim graf (sau graf neorientat)
perechea G = (X,U). Elementele din mulțimea X se numesc noduri sau vârfuri, iar elementele din mulțimea
U poartă numele de muchii ale grafului.

Exemplu X={1,2,3,4,5};
U={(1,3),(2,3),(2,5),(3,5)};

Un graf se reprezintă grafic printr-o mulțime de puncte corespunzătoare vârfurilor grafului si o mulțime de
segmente corespunzătoare muchiilor.

1 3

5 2

Dacă pentru un graf există o reprezentare în care să nu existe două segmente care să se intersecteze, atunci
spunem că graful reprezentat este un graf planar.

Exercitiu: G = ({1, 2, 3, 4}, {(1,2), (1,3), (1,4), (2,3), (2,4), (3,4)}). Desenati graful si spuneti daca este
planar.
2
Pornind de la definiție observăm că dacă X are n elemente, atunci U are cel mult C n elemente.

Dacă A este o mulțime, vom nota prin |A| numărul de elemente ale mulțimii.

Definiție. Fie G = (X,U) un graf. |X| este ordinul grafului G, iar |U| este dimensiunea grafului G.

Definiție. Fie G = (X,U) un graf. Doua varfuri legate printr-o muchie se numesc adiacente si sunt
extremitatile muchiei respective.. Daca x, y ∈X si {x, y} ∈U muchia {x,y} este incidenta cu varful x
si varful y.

Definiție. Fie G = (X,U) un graf si x ∈ X un nod fixat. Prin gradul nodului x înțelegem numărul muchiilor
incidente lui x si notăm acest număr cu d(x). Dacă d(x)=1 spunem că x este nod terminal. Dacă d(x) = 0
spunem că x este nod izolat.

1 6 Exemplu Fie graful din figura urmatoare:

5 Nodul 6 este nod izolat.


2 Nodul 5 este nod terminal
3 4
Propoziția 1. Fie G = (X,U) un graf în care |U|=m . Atunci ∑d ( x) = 2m .
x∈X

Propoziția 2. Pentru orice graf G = (X,U), numărul vârfurilor de grad impar este par.

Definiție.Fie G = (X,U) un graf. Numim graf parțial al lui G, graful G’=(X,V), unde V⊂U.

Definiție. Fie G = (X,U) un graf. Numim subgraf în G, graful G”=(Y,V) , în care Y⊂X, iar V = {{x, y} ∈
U| x, y ∈ Y} .

Definiție. Fie G = (X,U) un graf cu n vârfuri (|X|=n). Spunem că G este un graf complet, dacă oricare ar fi
x,y ∈ X, avem {x, y} ∈ U (orice două vârfuri din G sunt conectate sau adiacente).
Graful complet cu n vârfuri se notează prin K n .

Propoziția 3. Numărul muchiilor lui K n este C n2 .

Definiție. Fie G = (X,U) un graf. Dacă există X1 si X2 astfel încât X 1 ∩ X 2 = φ si X = X 1 ∪ X 2 ( X admite


o partiție din doua blocuri X1 si X2) si orice muchie din G uneste un nod din X1 cu unul din X2 (oricare ar fi e
= {x, y} ∈ U , dacă x ∈ X 1 , atunci y ∈ X 2 ) spunem că G este graf bipartit.

Definiție. Fie G = (X,U) un graf bipartit cu partițiile X1 si X2. Dacă |X1| = p si |X2| = q si dacă fiecare vârf din
X1 este adiacent cu toate vârfurile din X2 (pentru orice x ∈ X 1 si orice y ∈ X 2 avem {x, y}∈U ) spunem că
G este un graf bipartit complet, notat K p , q .

Propoziția 4. Graful bipartit complet K p ,q are pq muchii.

Definiție. Fie G = (X,U) un graf. Numim lanț în G o succesiune de vârfuri L = ( x 0 , x1 ,..., x r ) = x 0 x1 ... x r ,
astfel încât pentru orice i = 0,1,..., r −1, xi xi +1 ∈U (adică o succesiune în care oricare două vârfuri vecine
din lanț sunt adiacente).

Fie G = (X,U) este un graf si L = x 0 x1 ... x r un lanț în G . Vârfurile x 0 si x r se numesc extremitățile


lanțului L, iar r se numeste lungimea lanțului L, notată l (L) = r (lungimea unui lanț este dată de numărul
muchiilor sale sau de numărul vârfurilor mai puțin unul).

Definiție. Fie G = (X,U) un graf. Lanțul L din G se numeste lanț elementar dacă pentru orice
0 ≤ i , j ≤ r , i ≠ j , avem x i ≠ x j (lanțul trece prin noduri distincte).

Definiție. Fie G = (X,U) un graf. Lanțul L din G se numeste lanț simplu dacă pentru orice
0 ≤ i, j ≤ r −1, i ≠ j , avem {xi , xi +1 } ≠{x j , x j +1 } (toate muchiile sale sunt distincte).

Propoziția 5. Fie G = (X,U) un graf si L un lanț în G . Dacă L este lanț elementar, atunci L este lanț simplu.

1.2. Grafuri orientate

Definiție. Fie X o mulțime finită si nevidă. Numim graf orientat (digraf) orice pereche G = (X,U) în care U
⊂ X × X este o mulțime finită de perechi ordonate cu componente din X (U este o relație binară pe X ).

Elementele mulțimii X vor fi numite vârfuri sau noduri. Elementele mulțimii U se numesc arce. Orice arc
are forma (a,b) , în care a se numeste extremitate inițială, iar b se numeste extremitate finală a arcului
(a,b) .
Un graf orientat se reprezinta grafic printr-o mulțime de puncte corespunzătoare vârfurilor si printr-o
mulțime de segmente orientate (săgeți) corespunzătoare arcelor. O săgeată este orientata de la extremitatea
inițiala spre extremitatea finală a arcului pe care îl reprezintă.

Dacă u = (x,y) ∈ U spunem că x si y sunt adiacente în G si că nodurile x si y sunt incidente arcului u sau că
arcul u este incident nodurilor x si y. Mai exact, spunem că u este incident exterior nodului x (u pleacă sau
iese din x ) si că u este incident interior nodului y (u ajunge sau intră în y ). Arcul (x,y) ∈ U se mai notează
si prin xy .

Exemplu
Fie graful G=(X,U), unde X = { x1 , x 2 , x 3 , x 4 } şi U = { ( x1 , x 2 ) , ( x1 , x3 ) , ( x 2 , x 4 ) , ( x3 , x 2 ) , ( x3 , x 4 ) } .
Un graf poate fi reprezentat grafic astfel:
- se plasează în plan cele patru varfuri în poziţii distincte oarecare;
- pentru fiecare arc ( xi , x j ) ∈ A , punctele x i şi x j se unesc printr-un segment orientat (printr-o
săgeată ce porneşte din x i şi ajunge în x j ).
Să reprezentăm grafic graful din exemplul considerat:
X2

X1
X3

X4

Definiție. Fie G = ( X,U ) un graf orientat si x ∈ X un nod fixat.


 Numim grad interior al lui x, numărul arcelor incidente interior lui x, adică mărimea
d − ( x ) =| {( y, x ) ∈U | y ∈ X } | .
 Numim grad exterior al lui x, numărul arcelor incidente exterior lui x, adică mărimea
d + ( x ) =| {( x, y ) ∈U | y ∈ X } | .
 Prin gradul nodului x înțelegem numărul total al arcelor incidente lui x, adică mărimea
d ( x) = d − ( x) + d + ( x) .
 Dacă d (x) = 0 spunem că x ∈ X este vârf izolat.
 Dacă d − ( x) = 1 si d + ( x) = 0 spunem că x ∈ X este vârf terminal; dacă d − ( x) = 0 si d + ( x) = 1
spunem că x ∈ X este vârf inițial.

Definiție. Fie G = (X,U) un graf orientat si A ⊂ X o mulțime de vârfuri.


 Gradul interior lui A este numărul arcelor ce intră în A si care au nodul inițial în afara lui A, adică
mărimea d − ( A) =| {( y , x) ∈U | y ∉ A, x ∈ A} | .
 Gradul exterior lui A este numărul arcelor ce ies din A si au nodul terminal în afara lui A, adică
mărimea d + ( A) =| {( x, y ) ∈U | y ∉ A, x ∈ A} | .
 Gradul total al lui A este d ( A) = d − ( A) + d + ( A) .

Observații.
1) Evident, pentru orice A ⊂ X avem d − ( A) ≤ ∑ d − ( x) , deoarece s-ar putea ca anumite arce care ies din
x∈A

A să aibă extremitatea finală tot în A, arce care nu se numără la determinarea valorii d −( A) .


2) Evident, pentru orice A ⊂ X avem d + ( A) ≤ ∑d + ( x ) , deoarece s-ar putea ca anumite arce care intră în
x∈A

A să aibă extremitatea inițială tot în A, arce care nu se numără la determinarea valorii d +( A) .


Din 1) si 2) rezult că d ( A) ≤ ∑
x∈A
d ( x) .
Definiție. Fie G = (X,U) un graf orientat. Numim graf orientat parțial al lui G graful orientat G = (X,V) în
care V ⊂U.
Un graf orientat parțial al lui G se obține prin suprimarea anumitor arce ale lui G .

Definiție. Fie G = (X,U) un graf orientat. Numim subgraf orientat al lui G, graful orientat H = (Y,V) în
care Y⊂X, iar V = {(x, y)∈U | x, y∈Y} (mul țimea tuturor arcelor lui G cu ambele extremită ți în Y ).
Un subgraf orientat se obține suprimând anumite vârfuri din G si eliminând toate arcele incidente vârfurilor
suprimate.

Definiție. Fie G = (X,U) un graf orientat. Dacă pentru orice x,y∈ X avem (x,y)∈U sau (y,x)∈U spunem că
G este graf orientat complet.
Un graf orientat complet cu n vârfuri se notează cu K n .

Observație. În cazul grafurilor neorientate, pentru un n∈ℕ, n ≥ 2, există un singur graf complet cu n
vârfuri, notat K n . În cazul grafurilor orientate pentru un n∈ℕ, n ≥ 2 dat, există mai multe grafuri orientate
complete cu n vârfuri, ele diferind fie prin orientarea arcelor, fie prin numărul de arce ce unesc două vârfuri,
număr ce poate fi 1 sau 2.

Definiție. Fie G = (X,U) un graf orientat. Numim drum în G o succesiune de vârfuri d = ( x0 , x1 ,..., xr )
astfel încât pentru orice i = 0,1,..., r −1, xi xi +1 ∈U (sau o succesiune de arce care au acelasi sens,
d =(u1 , u2 ,..., u p ) , cu proprietatea că pentru orice i =1,2,..., p −1, ui si ui +1 au o extremitate comună,
mai exact extremitatea finală a lui ui coincide cu extremitatea inițială a lui ui +1 .
Fie d = ( x0 , x1 ,..., xr ) un drum în graful G = (X,U) . x0 se numeste extremitatea inițială, iar xr
extremitatea finală a drumului d.

Definiție. Drumul d = ( x0 , x1 ,..., xr ) din graful G = (X,U) se numeste elementar dacă pentru orice i, j =
0,1,..., r , i ≠ j , avem xi ≠ x j (drumul trece prin noduri distincte).

Definiție. Fie G = (X,U) un graf orientat. Numim lanț în G, o secvență de noduri L =[ x0 , x1 ,..., xr ] cu
proprietatea că pentru orice i = 0,1,..., r −1 avem xi xi +1 ∈U sau xi +1 xi ∈U (sau o succesiune de arce
L =[u1 , u 2 ,..., u p ] astfel încât pentru orice i =1,2,..., p −1, arcele ui si ui +1 au o extremitate comună - nu
se mai pune condiția ca arcele să aibă acelasi sens, ca la drumuri).

Observație. Din definiție rezultă imediat că orice drum într-un graf orientat este în acelasi timp si lanț în
graful orientat respectiv.

Definiție. Fie G = (X,U) un graf orientat. Pentru orice x, y∈ X spunem că y este accesibil din x sau y este
atins din x dacă si numai dacă există d = ( x0 , x1 ,..., xr ) un drum de capete x si y .

II. TIPURI PARTICULARE DE GRAFURI

Definiție. Se numeste multigraf un graf neorientat în care cel puțin două vârfuri sunt unite prin muchii
multiple.

Definiție. Graful orientat G = (X,U) se numeste reflexiv (simetric, antisimetric, total, tranzitiv) dacă si
numai dacă relația binară U este relație binară reflexivă ( simetrică,antisimetrică, totală, tranzitivă).

O relatie binara pe o multime A este o submultime a produsului cartezian AxA si se noteaza cu ρ ⊆ A × A ,


iar pentru (a, b) ∈ρ scriem aρb . O relatie binara ρ ⊆ A × A se numeste:
• reflexiva, daca ∀a ∈A, aρa
• simetrica, daca ∀a, b ∈A, aρb ⇒bρa
• antisimetrica, daca ∀a, b ∈A, aρb si bρa implica a=b
• totala, daca ρ = A × A
• tranzitiva, daca ∀a, b, c ∈A, aρb si bρc implica aρc

Definiție. Fie G = (X,U) un graf orientat. Dacă pentru fiecare x∈X se asociază o etichetă pentru identificare
spunem că G este un graf orientat etichetat.

Observăm că la toate grafurile de mai sus am folosit o numerotare a vârfurilor. Numerele folosite pot fi
considerate etichete pentru vârfuri si astfel grafurile pot fi considerate drept grafuri etichetate.

Definiție. Fie G = (X,U) un graf orientat. G se numeste graf orientat marcat sau rețea dacă fiecărui u∈U i
se asociază o marcă mu . În acest caz, U⊂X×M×X , M fiind mulțimea mărcilor asociate arcelor. Dacă
( x,m,y)∈X×M×X, atunci arcul x → y se marchează cu m si se reprezinta prin x → m
y.

Definiție. Numim rețea etichetată un graf orientat marcat si etichetat.

Graful de mai sus, având vârfurile numerotate si muchiile marcate poate fi considerat si un exemplu de rețea
etichetată.

2.1. Grafuri conexe

Definiție. Graful neorientat G = (X,U) se numeste conex dacă si numai dacă oricare ar fi două noduri x,
y∈X , x≠y , există cel puțin un lanț în G, L = ( x0 , x1 ,..., xr ) de extremități x si y.

Definiție. Fie G = (X,U) un graf neorientat. Numim componenta conexă a lui G, un subgraf conex C
=(Y,V) al său, si pentru orice x∈Y, subgraful obținut luând mulțimea de vârfuri Y \{x} nu este conex
(subgraful C este maximal în raport cu proprietatea de conexitate).

Fie G = (X,U) un graf neorientat. Pentru x, y∈ X spunem că x este conectat cu y dacă există un lanț ce le
uneste, adică există un lanț L = ( x0 , x1 ,..., xr ) de extremități x si y
Pe mulțimea X definim relația binară ~⊂ X × X , dată prin x ~ y dacă si numai dacă ( x = y sau x este
conectat cu y ).

Propoziția 1. Relația " ~ " definita mai sus este o relație de echivalență (reflexiva, simetrica si tranzitiva).
Propoziția 2. Fie G = (X,U) un graf în care |X| = n , |U| = m si n ≥2. Dacă G este conex, atunci m ≥n −1.

Noțiunea de graf conex este valabilă si pentru grafurile orientate. Definiția este următoarea:

Definiție. Graful orientat G = ( X,U ) se numeste conex dacă si numai dacă oricare ar fi două noduri x, y∈ X
, x≠y , există cel puțin un lanț în G, L = ( x0 , x1 ,..., xr ) de extremități x si y .

Dacă în definiția grafului conex pentru grafuri orientate înlocuim condiția de existență a unui lanț cu cea de
existență a unui drum se obține următoarea noțiune.

Definiție. Graful orientat G = (X,U) se numeste tare conex dacă si numai dacă oricare ar fi două noduri x,
y∈ X , x≠y , există cel puțin un drum în G, d = ( x0 , x1 ,..., xr ) de extremități x si y.
O posibilitate de a determina dacă un graf neorientat este conex, sau determinarea efectivă a componentelor
conexe (sau problemele similare pentru grafurile orientate) constă în aplicarea unui algoritm de tip greedy.

Să considerăm întâi problema determinării conexității unui graf neorientat G = (X,U).


Algoritm 1.

1. Se consideră Y = X , V =U si se alege orice x∈ X pentru care considerăm B = {x}.


2. Dacă B =∅ , atunci algoritmul se termină generând un răspuns astfel:
a. Dacă V =∅ , atunci graful este conex
b. Dacă V ≠ ∅, atunci graful nu este conex (în plus se poate spune că mulțimea X \Y reprezintă
componenta conexă din care face parte si nodul x considerat la 1).
Altfel se continuă.
3. Se alege orice y∈B .
4. Pentru fiecare z∈Y \ B astfel încât {y, z}∈V considerăm B = B ∪{z} si V =V \{{y, z}}
5. Considerăm B = B \{y} si reluăm de la 2.

Asa cum se vede din pasul 2, algoritmul prezentat dă răspunsul la întrebarea „Este G un graf conex?”. De
asemenea, se poate determina componenta conexă a grafului G din care face parte un anumit nod specificat.
Acest lucru creează premizele realizării algoritmului de determinare a componentelor conexe, plecând de la
algoritmul 1.

Algoritm 2.

1. Se consideră Y = X , V =U, k = 0 .
2. Dacă V =∅ , atunci algoritmul se termină si componentele conexe ale grafului G sunt A1 , A2 ,..., Ak .
k

Vârfurile care nu sunt în  Ai sunt vârfuri izolate si formează fiecare în parte câte o componentă conexă a
i =1

grafului G (în plus valoarea pentru k arată dacă graful G este sau nu conex. Astfel pentru k =1 si A1 = X
graful este conex, altfel G nu este conex).
3. Alegem orice x∈Y . Fie k = k +1, Ak = φ , B = {x} .
4. Dacă B =∅ se trece la 8, altfel se continuă.
5. Se alege orice y∈B .
6. Pentru fiecare z∈Y \ B astfel încât {y, z}∈V considerăm B = B ∪{z} si V =V \{{y, z}} .
7. Considerăm B = B \{y} , Ak = Ak ∪{y} . Se trece la 4.
8. Se elimină din V orice muchie {a,b} pentru care a,b∈ Ak si din Y orice a∈ Ak . Se trece la 2.

2.2. Grafuri complementare si izomorfe

Definiție. Fie G = (X,U) un graf neorientat, numim complementarul lui G (graf complementar lui G ),
graful CG = ( X,CU), în care {x, y}∈CU dacă si numai dacă {x, y}∉U .

Definiție. Fie G = ( X,U ) si G’= ( X’,U’) două grafuri neorientate. Spunem că G si G′ sunt izomorfe, notăm
G ≅ G’ , dacă există o funcție bijectivă f : X → X’ astfel încât {x, y}∈U dacă si numai dacă { f ( x), f
( y)}∈U’.

Din definiție rezultă că două grafuri sunt izomorfe dacă au acelasi număr de vârfuri si se poate obține unul
din celălalt printr-o renumerotare a vârfurilor.

Definiții similare celor de mai sus sunt valabile pentru grafurile orientate.
Ele se obțin înlocuid muchiile cu arce.
Propoziția 3. Fie G = (X,U) si G’= ( X’,U’) două grafuri orientate. Atunci G ≅ G’ dacă si numai dacă CG ≅
CG’ .

2.3. Grafuri ciclice


Definiție. Fie G = (X,U) un graf neorientat. Numim ciclu în G un lanț L =[ x0 , x1 ,..., xr ] în care x0 = xr
(în care extremitățile coincid).

Definiție. Fie G = (X,U) un graf neorientat si L =[ x0 , x1 ,..., xr ] un ciclu. Spunem că L este ciclu
elementar dacă pentru orice 0 ≤i, j ≤r −1, i≠j, avem xi ≠ x j (toate vârfurile sale, exceptând extremitățile,
sunt distincte două câte două).

Definiție. Fie G = (X,U) un graf neorientat si L =[ x0 , x1 ,..., xr ] un ciclu. Spunem că L este ciclu simplu
daca pentru orice 0 ≤i, j ≤r −1, i≠j, avem {xi , xi +1} ≠{x j , x j +1} (toate muchiile sale sunt distincte două
câte două).

Definițiile de mai sus continuă să fie valabile si pentru grafurile orientate. Suplimentar intervin definițiile
care urmează.

Definiție. Fie G = (X,U) un graf orientat. Numim circuit în G un drum C = ( x0 , x1 ,..., xr ) în care x0 = xr
(în care extremitățile coincid).

Definiție. Fie G = (X,U) un graf orientat si C = ( x0 , x1 ,..., xr ) un circuit. Spunem că C este circuit
elementar dacă pentru orice 0 ≤i, j ≤r −1, i≠j, avem xi ≠ x j (toate vârfurile sale, exceptând extremitățile,
sunt distincte două câte două).

Definiție. Fie G = (X,U) un graf orientat si C = ( x0 , x1 ,..., xr ) un ciclu. Spunem că C este circuit simplu
daca pentru orice 0 ≤i, j ≤r −1, i≠j, avem ( xi , xi +1 ) ≠( x j , x j +1 ) (toate arcele sale sunt distincte două câte
două).

Definiție. Graful neorientat G = (X,U) se numeste ciclic dacă G conține cel puțin un ciclu si se numeste
aciclic în caz contrar.

Definiție. Fie G = (X,U) un graf orientat. Spunem că G este aciclic dacă G nu conține nici un circuit si ciclic
în caz contrar.

Propoziția 4. Fie G = (X,U) un graf neorientat. Dacă |U| ≥ |X|, atunci G este ciclic.

Definiție. Fie G = (X,U) un graf neorientat având k ≥ 1 componente conexe. Se numeste punte în G o
muchie m∈U pentru care graful parț ial G’ = (X ,U \{m}) are numărul de componente conexe mai mare
decât k .

Propoziția 5. Fie G = (X,U) un graf neorientat si m∈U . m este punte, dacă si numai dacă oricare ar fi ciclul
C =[ m0 , m1 ,..., mr ] în G dat prin muchiile sale, m ≠ mi pentru orice 1 ≤ i ≤ r.\

Propoziția 6. Fie G = (X,U) un graf orientat. G este tare conex dacă si numai dacă există un circuit C care
conține toate vârfurile grafului.

Definiție. Fie G = (X,U) un graf orientat. Definim V = {(x,y)∈U| ∃C circuit in G cu (x,y)∈C}. Graful parțial
H = (X,V) se numeste graful orientat ciclu al lui G .

Propoziția 7. Fie G = (X,U) un graf orientat si H = (X,V) graful ciclu al lui G . Fie Y⊂X si G’ = (Y,W)
subgraf. Atunci G’ este componentă tare conexă în G dacă si numai dacă G’ este componentă tare conexă în
H.

III. REPREZENTAREA GRAFURILOR

3.1. Reprezentare grafuri neorientate


Fie G=(X,U) un graf neorientat.
Exista mai multe modalitati de reprezentare pentru un graf neorientat, folosind diverse tipuri de structuri de
date. Cele mai cunoscute forme de reprezentare ale unui astfel de graf sunt: matricea de adiacenta, listele
vecinilor si vectorul muchiilor.

3.1.1. Matricea de adiacenta

Matricea de adiacentã asociatã unui graf neorientat cu n noduri este o matrice patratica cu n linii si n
coloane, in care elementele a[i,j] se definesc astfel: a[i,j]=1 daca exista (i,j) in U, cu x diferit de y si 0 daca
nu exista (i,j) in U.

1, daca [i,j]∈U
a[i,j] =
0, altfel

Proprietatile matricei de adiacenta:


• Este o matrice simetrica;
• Pe diagonala principala are toate elementele egale cu 0;
• Suma elementelor pe linia sau coloana i este egala cu gradul nodului i;
• Daca elementele pe linia/coloana i sunt toate egale cu 0 atunci nodul este izolat;
• Daca toate elementele din matrice,mai putin cele de pe diagonala principala, sunt 1 inseamna ca
graful este complet.

Exemplu Fie graful din figura de mai jos:

1 6

5
2
3 4

Graful de mai sus are 6 noduri si 5 muchii.


Matricea de adiacenta este simetrica si patratica avand 6 linii si 6
coloane, iar diagonala principala contine numai valori nule :

nodul 1 are gradul 2


 0 1 0 1 0 0
nodul 2 are gradul 2
 
nodul 3 are gradul 3
nodul 4 are gradul 2
 1 0 1 0 0 0
nodul 5 are gradul 1  0 1 0 1 1 0
nodul 6 are gradul 0 A=  
Pentru a prelucra graful se citesc:
 1 0 1 0 0 0
6- reprezentand n, numarul de noduri  0 0 1 0 0 0
5- reprezentand m, numarul de muchii
 
5 perechi x-y reprezentand extremitatile celor 5 muchii:
 0 0 0 0 0 0
1-2 => a[1,2]=a[2,1]=1
1-4 => a[1,4]=a[4,1]=1
 
2-3 => a[2,3]=a[3,2]=1
3-4=> a[3,4]=a[4,3]=1
3-5 => a[3,5]=a[5,3]=1
3.1.2. Listele de adiacenta a nodurilor

Reprezentarea in calculator a unui graf se poate face utilizand listele de adiacenta a varfurilor, adica pentru
fiecare varf se alcatuieste lista varfurilor adiacente cu el. Listele de adiacenta pot fi reprezentate cu ajutorul
tablourilor sau ca structuri dinamice de date (liste inlantuite).
Pentru graful de mai sus avem:

Lista vecinilor nodului 3: 2, 4, 5 (noduri adiacente)

Nodul 6 nu are vecini (este izolat)


Pentru intreg graful vom avea mai multe liste :

Nodul 1 : 2 4
Nodul 2 :
1 3
Nodul 3 :
2 4 5
Nodul 4 : 1 3
Nodul 5 : 3

Ordinea nodurilor in cadrul unei liste nu este importanta


Pentru a genera o astfel de lista vom defini tipul nod :

struct nod {
int nd;
nod *next;
};

Toate listele se vor memora utilizand un vector de liste :

nod *L[20];
Datele de intrare : numarul de noduri si muchiile se vor citi din fisier :

O solutie de implementare este urmatoarea :

#include<conio.h>
#include<fstream.h>
struct nod{
int nd;
nod *next;
};

nod *L[20];

void afisare(int nr_nod) //afiseaza lista vecinilor nodului nr_nod


{
nod *p=L[nr_nod];
if(p==0)
cout<<nr_nod<<" este izolat "<<endl;
else
{cout<<"lista vecinilor lui "<<nr_nod<<endl;
nod *c=p;
while(c)
{cout<<c->nd<<" ";
c=c->next;}
cout<<endl;}
}
void main()
{
fstream f;
int i,j,n;
nod *p,*q;
f.open("graf.txt",ios::in); //citirea datelor din fisier
f>>n;
while(f>>i>>j)
{ p=new nod; //se adauga j in lista vecinilor lui i
p->nd=j;
p->next=L[i];
L[i]=p;
q=new nod; //se adauga i in lista vecinilor lui j
q->nd=i;
q->next=L[j];
L[j]=q;
}
f.close();
cout<<endl<<"listele de adiacente ";
for(i=1;i<=n;i++)
afisare(i);
}

Observatie : In exemplul anterior adaugarea unui nou element in lista se face inainte celorlalte din lista
corespunzatoare.
Aceste doua moduri de reprezentare (prin matrice de adiacenta si prin liste de vecini) se folosesc dupa natura
problemei. Adica, daca in problema se doreste un acces frecvent la muchii, atunci se va folosi matricea de
adiacenta; daca numarul de muchii care se reprezinta este mult mai mic decat nxn, este de preferat sa se
folosesca listele de adiacenta, pentru a se face economie de memorie.

3.1.3. Vectorul muchiilor

Fiecare muchie a grafului poate fi privita ca o inregistrare cu doua componente: cele doua varfuri care
constitue extremitatile muchiei. Notand aceste extremitati cu nod1 si nod2, putem defini tipul de date
tmuchie, astfel:

struct tmuchie{
int nod1,nod2;
};

Graful in ansamblul sau, este o multime de muchii, adica o multime de elemente de tipul tmuchie. In
consecinta definim graful ca un “vector de muchii”, adica un vector cu elementele de tipul tmuchie:

tmuchie v[25];

3.2. Matrici asociate grafurilor

Daca G = ({v1, . . . , vn}, {e1, . . . , em}) este un graf, atunci

Matricea de adiacenta a grafului G este matricea A = (aij)n×n, unde

 1 d a vci s avi j s u an dt i a c e n t e
ai j = 
0a l t f e l
Matricea de incidenta a grafului G este matricea B = (bij)n×m, unde
 1 d a vci saei j s u i n tc i d e n t e
bi j = 
0a l t f e l
In cazul digrafurilor, se pot asocia similar astfel de matrici, in care, evident se poate indica si
orientarea arcelor, folosind elementele 0, 1 si -1.

Pentru graful din figura de mai jos,

matricea de adiacenta este:

 0 11 0 0
 
 1 0 0 11 
A =  1 0 0 11 
 
 0 11 0 1 
 0 111 0 
 
iar matricea de incidenta:
 0 0 0 0 0 1 1
 
1 0 1 0 0 0 1
B= 0101010
 
 0 0 111 0 0 
 11 0 0 1 0 0 
 
Valorile proprii si polinomul caracteristic ale matricii de adiacenta se numesc valorile proprii ale grafului,
respectiv, polinomul caracteristic al grafului.

IV. Parcurgerea grafurilor

Graph search- paradigma algoritmica utilizata pentru a desemna o metoda sistematica de parcurgere a
multimii varfurilor la care se poate ajunge prin drumuri intr-un (di)graf de la un varf fixat.
Dat fiind G = (V,E) un (di)graf cu multimea varfurilor V = {1, . . . , n} si s ∈ V , se cere sa se genereze
”eficient” multimea S = {v ∈ V | ∃D drum in G de la s la v}.
Parcurgerea unui graf neorientat indica posibilitatea de a ajunge o singura data in fiecare varf al grafului,
pornind de la un varf dat “xk” si parcurgand muchii adiacente. Aceasta operatiune poarta numele de vizitare
sau traversare a varfurilor grafului si este efectuata cu scopul prelucrarii informatiei asociata varfurilor.
Parcurgerea grafurilor orientate este similara cu a grafurilor neorientate, se tine cont insa de orientare.
Prezentam succint cele doua tehnici principale de parcurgere.

4.1. Parcurgerea în „lăţime” (Breadth First - BF)

Numele provine din limba engleza (Breadth First-“in latime”) si principiul este: se viziteaza intai varful
initial, se exploreaza toate varfurile adiacente lui, se trece apoi la primul varf adiacent si se exploreaza toate
varfurile adiacente acestuia si neparcurse inca, s.a.m.d.
Fiecare varf se parcurge cel mult odata.
De exemplul pentru garful din figura de mai jos, se va proceda in felul urmator:
se porneste din nodul 1, (se poate incepe de la oricare alt nod)

1 6

se exploreaza in continuare vecinii acestuia : nodul 2 si apoi 4,


5
21 6
se obtine 1,2,4
3 4
dupa care din 2 se exploreaza nodul adiacent acestuia 3. Nodul 1 nu se mai viziteaza odata
5
2
1 6
se obtine 1,2,4,3

In continuare ar trebui parcursi vecinii lui 4 (1,2,4,3 ) dar acesta nu mai are vecini
5
nevizitati si se trece la vecinii lui 3 : 1,2,4,3 respectiv nodul 5 :

2
1 6
3
se obtine 1, 2, 4, 3, 5 4
Varful 6 ramane neparcurs
5
Daca se parcurge graful incepand de la varful 2, solutia este : 2,3,4,5, in timp ce parcurgerea incepand cu 4
va retine doar varful 4

Exemplu1:
2
Pentru graful din figura următoare ordinea de parcurgere a nodurilor cu metoda BF, când se pleacă din
vârful 1 este următoarea: 1,2,3,4,5.

1 3 4
2 3

Dacă se pleacă din nodul 2, lista


vârfurilor obţinută în urma parcurgerii
BF este următoarea: 2,1,4,5,3.

Exemplu 2:
1

2 3

6 4 7 5
- pentru acest graf, pornind din nodul 4, continutul cozii va fi: 4,1,3,2,5,6,7

Algoritmul

Se va folosi o coada in care se inscriu nodurile in forma in care sunt parcurse: nodul initial varf (de la care
se porneste), apoi varfurilr a,b,..., adiacente lui varf, apoi cele adiacente lui a, cele adiacente lui b,... ,s.a.m.d.
Coada este folosita astfel:
- se incarca primul varf in coada;
- se afla toate varfurile adiacente cu primul nod si se introduc dupa primul varf
- se ia urmatorul nod si i se afla nodurile adiacente
- procesul se repeta pana cand se ajunge la sfarsitul cozii
-Graful se va memora utilizand matricea de adiacenta a[10][10]
-pentru memorarea succesiunii varfurilor parcurse se va folosi un vector c[20] care va functiona ca o coada
-pentru a nu parcurge un varf de doua ori se va folosi un vector boolean viz[20] care va retine :
- viz[k]=0 daca varful k nu a fost vizitat inca
- viz[k]=1 daca varful k a fost vizitat
-doua variabile : prim si ultim vor retine doua pozitii din vectorul c si anume :
- prim este indicele componentei pentru care se parcurg vecinii (indexul
componentelor marcate cu rosu in sirurile parcurse anterior ). Prin urmare Varf=c[prim], este elementul
pentru care se determina vecinii (varfurile adiacente)
-ultim este pozitia in vector pe care se va face o noua inserare in vectorul c
(evident, de fiecare data cand se realizeaza o noua inserare se mareste vectorul)
-vecinii unui varf se « cauta » pe linia acestui varf : daca a[varf][k]=1 inseamna ca varf si k sunt adiacente.
Pentru ca varful k sa fie adaugat in coada trebuie ca varful sa nu fi fost vizitat : viz[k]=0

Algoritmul consta in urmatorii pasi:

1) se prelucreaza varful initial k;


1) se adauga varful k in coada;
2) varful k se considera vizitat;
2) cat timp coada este nevida se executa:
1) pentru toti vecinii j nevizitati inca ai varfului k, executa:
1) se adauga varful j in coada;
2) varful j se considera vizitat;
2) varful j devine varful k;
3) se afiseaza continutul cozii;
#include<fstream.h>
#include<conio.h>

int a[10][10],c[20],viz[10];
int n,m,prim,ultim,varf;

void bf_iterativ() //parcurgerea in latime


{int k;
while(prim<=ultim)
{varf=c[prim];
for(k=1;k<=n;k++)
if(a[varf][k]==1&&viz[k]==0) //il adaug pe k in coada daca este vecin pt. varf si nu a fost vizitat
{ultim++;
c[ultim]=k;
viz[k]=1;}
prim++;
}
}

void main()
{clrscr();
int x,y;
fstream f; //memorare graf in matrice de adiacenta
f.open("muchii.txt",ios::in);
f>>n>>m;
for(int i=1;i<=m;i++)
{f>>x>>y;
a[x][y]=1;
a[y][x]=1; //numai pentru grafuri neorientate
}

cout<<"matricea de adiac "<<endl; // afisare matrice de adiacenta


for( i=1;i<=n;i++)
{for(int j=1;j<=n;j++)
cout<<a[i][j]<<" ";
cout<<endl;
}

int nd;
prim=ultim=1;
cout<<"varful de inceput=";
cin>>nd; // varful de la care se porneste parcurgerea
viz[nd]=1;
c[prim]=nd;
bf_iterativ();
for(i=1;i<=ultim;i++) //afisarea cozii
cout<<c[i]<<" ";
getch();
}

Varianta recursiva de parcurgere se obtine modificand functia de parcurgere iterativa adaugand conditia
necesara autoapelului:

void bf_recursiv() //parcurgerea in latime


{int k;
if(prim<=ultim)
{varf=c[prim];
for(k=1;k<=n;k++)
if(a[varf][k]==1&&viz[k]==0) //il adaug pe k in coada daca este vecin pt. varf si nu a fost vizitat
{ultim++;
c[ultim]=k;
viz[k]=1;}
prim++;
bf_recursiv();
}
}

Parcurgerea in latime a grafurilor memorate prin liste este similara cu diferenta ca vecinii unui nod adaugat
in coada se cauta in lista corespunzatoare lui :

#include<conio.h>
#include<fstream.h>
struct nod
{int nd;
nod *next;};

nod *L[20];
int viz[100]; //marchez cu 1 nodurile vizitate
int m,n;
int prim,ultim,C[100];

void bfi_lis()
{int varf,nr;
nod *p;
while(prim<=ultim)
{varf=C[prim];
p=L[varf]; // se parcurge lista elementelor din varful cozii
while(p)
{nr=p->nd;
if(viz[nr]==0) //numai daca nu a fost vizitat
{ultim++; //maresc coada
C[ultim]=nr; //il adaug in coada
viz[nr]=1;}; //il marchez ca fiind vizitat
p=p->next;
}
prim++; //avansez la urmatorul varf din coada
}
}

void afisare(int nr_nod)


{nod *p=L[nr_nod];
if(p==0)
cout<<nr_nod<<" este izolat "<<endl;
else
{cout<<"lista vecinilor lui "<<nr_nod<<endl;
nod *c=p;
while(c)
{cout<<c->nd<<" ";
c=c->next;}
cout<<endl;}
}

void main()
{fstream f;
int i,j;
nod *p,*q;
f.open("muchii.txt",ios::in);
clrscr();
f>>n>>m;

while(f>>i>>j)
{p=new nod;
p->nd=j;
p->next=L[i];
L[i]=p;
}

f.close();

cout<<endl<<"listele de adiacente ";

for(i=1;i<=n;i++)
afisare(i);

int ndr;
cout<<endl<<"nodul de inceput ";
cin>>ndr;
viz[ndr]=1;
prim=ultim=1;
C[prim]=ndr;
cout<<endl<<"parcurgere in latime "<<endl;
bfi_lis();
for(i=1;i<=ultim;i++)
cout<<C[i]<<" ";
getch();
}

Functia recursiva :
void bfr_lis()
{int varf,nr;
nod *p;
if(prim<=ultim)
{varf=C[prim];
p=L[varf];// se parcurge lista elementelor din varful cozii
while(p)
{nr=p->nd;
if(viz[nr]==0)//numai daca nu a fost vizitat
{ultim++;//maresc coada
C[ultim]=nr;//il adaug in coada
viz[nr]=1;};//il marchez ca fiind vizitat
p=p->next;}
prim++; //avansez la urmatorul nod din coada
bfr_lis();
}
}

Probleme propuse :

1.Sa se parcurga graful in latime pornind pe rand de la toate varfurile


2. Sa se determine daca pornind de la nodul x se poate ajunge la nodul y
3. Sa se determine daca se poate parcurge pornind de la un nod tot graful

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