Sunteți pe pagina 1din 78

CAPITOLUL I

ELEMENTE DE TEORIA GRAFURILOR



I.1. Graful

Se numete graf (G) o pereche ordonat de mulimi (X,U), unde X este o mulime finit
i nevid, iar U o mulime de perechi formate cu elemente distincte din mulimea X
(familie de submulimi cu dou elemente din mulimea X).
Terminologie:
- Elementele mulimii X se numesc vrfuri sau noduri. Mulimea X se mai numete
i mulimea vrfurilor sau mulimea nodurilor grafului G. Ea este de forma:
X={x
1
, x
2
, x
3
, ..., x
j
, ..., x
n
}
unde x
j
reprezint nodul i al grafului G care are n noduri.
- Ordinul grafului reprezint numrul de noduri ale grafului, n:
ordinul grafului = card(X) = n
- Elementele mulimii U sunt perechi de noduri, adic submulimi cu dou elemente
din mulimea X i se noteaz cu u
k
. Elementul u
k
este definit de perechea de forma
{x
i
, x
j
}, unde x
i
, x
j
X i x
i
x
j
(elemente distincte din mulimea X). Elementul u
k

leag nodurile x
i
i x
j
i se noteaz astfel: [x
i
, x
j
]. Mulimea U este de forma:
U={u
1
, u
2
, u
3
, ..., u
k
, ..., u
m
}
Clasificarea grafurilor:
Criteriul de clasificare folosit este proprietatea de simetrie a mulimii U.
Mulimea U are proprietatea de simetrie dac i numai dac, pentru orice pereche de
noduri (x
i
, x
j
), dac { x
i
, x
j
}U, atunci i { x
j
, x
i
}U.
n funcie de proprietatea de simetrie, grafurile se clasific n:
- Grafuri neorientate. Un graf G=(X,U) este un graf neorientat dac mulimea U
are proprietatea de simetrie. Mulimea U este format din perechi neordonate { x
j
,
x
i
}.
- Grafuri orientate. Un graf G=(X,U) este un graf orientat dac mulimea U nu are
proprietatea de simetrie. Mulimea U este format din perechi ordonate { x
j
, x
i
}.
Studiu de caz
Scop: identificarea tipului de graf folosit pentru a rezolva problema.
Enunul problemei 1. Pe harta unui jude exist mai multe localiti care sunt legate prin
osele pe care se circul n ambele sensuri. S se identifice traseele pe care se poate
ajunge de le localitatea A la localitatea B.
Nodurile grafului sunt localitile. Relaia care se stabilete ntre nodurile grafului este:
nodul x este n relaie cu nodul y, dac exist o osea care leag direct localitatea asociat
nodului x cu localitatea asociat nodului y. Relaia are proprietatea de simetrie, deoarece
oseaua care leag direct localitatea asociat nodului x cu localitatea asociat nodului y
leag direct i localitatea asociat nodului y cu localitatea asociat nodului x. Pentru
reprezentarea cilor de comunicaie dintre localiti se va folosi un graf neorientat.
Enunul problemei 2. Pe harta unui cartier exist mai multe intersecii care sunt legate de
strzi. Pe unele strzi se poate circula n ambele sensuri, pe alte strzi numai ntr-un
anumit sens. S se identifice traseele prin care se poate ajunge de la intersecia A la
intersecia B.
Nodurile grafului sunt interseciile. Relaia care se stabilete ntre nodurile grafului este:
nodul x este n relaie cu nodul y, dac exist trafic care leag direct intersecia asociat
nodului x cu intersecia asociat nodului y (se poate circula de la nodul x la nodul y).
Relaia nu are proprietatea de simetrie deoarece, dac exist o strad care leag direct
intersecia asociata nodului x cu intersecia asociat nodului y i pe aceast strad exist
trafic de la nodul x la nodul y, nu este obligatoriu ca pe acea strad s existe trafic i de la
nodul y la nodul x. Pentru reprezentarea traficului auto dintre intersecii se va folosi un
graf orientat.
Enunul problemei 3. La nivelul unui grup de persoane se face un studiu social. ntre
persoane se stabilesc relaii de prietenie, dar i relaii de simpatie. S se descrie cu
ajutorul grafului relaiile intre persoane.
Nodurile grafului sunt membrii grupului de persoane. ntre persoane se pot stabili
relaiile:
-Relaia de prietenie este o relaie definit astfel: persoana x este n relaie cu persoana y,
dac este prieten cu ea. Relaia este simetric deoarece, dac persoana x este prieten cu
persoana y, atunci i persoana y este prieten cu persoana x (relaia de prietenie
presupune reciprocitate). Pentru reprezentarea relaiilor de prietenie dintre membrii
grupului se va folosi un graf neorientat.
-Relaia de simpatie este o relaie definit astfel: persoana x este n relaie cu persoana y,
dac o simpatizeaz. Relaia nu este simetric deoarece, dac persoana x simpatizeaz
persoana y, nu este obligatoriu ca persoana y s simpatizeze persoana x (relaia de
simpatie nu presupune reciprocitate). Pentru reprezentarea relaiilor de simpatie dintre
membrii grupului se va folosi un graf orientat.

I.1.1. Graful neorientat

Elementele mulimii U (perechile de noduri) se numesc muchii. Mulimea U se mai
numete i mulimea muchiilor grafului G. O muchie, fiind un element din mulimea U,
este determinat de o submulime cu dou elemente din mulimea X: muchia k a grafului
(u
k
), care unete nodurile x
i
i x
j
, este determinat de submulimea {x
i
, x
j
} i se noteaz cu
[x
i
, x
j
]. [x
i
, x
j
] i [x
j
, x
i
] reprezint aceeai muchie a grafului. Graful G are m muchii:
numrul de muchii = card(U) = m
Numim noduri adiacente orice pereche de noduri care formeaz o muchie - {x
i
, x
j
}U.
Fiecare dintre cele dou noduri (x
i
i x
j
) este nod incident cu muchia u
k
= [x
i
, x
j
].
Nodurile vecine unui nod x
i
sunt toate nodurile x
j
care sunt adiacente cu el.
Se numete nod extrem al unei muchii oricare dintre cele dou noduri care se gsesc la
captul muchiei. Nodurile x
i
, i x
j
sunt extremitile muchiei [x
i
, x
j
].
Se numesc muchii incidente dou muchii u
i
i u
j
care au o extremitate comun - nodul x
k
.
Un graf neorientat G este definit de o pereche de mulimi: mulimea nodurilor sale - X
i mulimea muchiilor sale - U. El poate fi considerat ca o mulime de noduri din care
unele pot fi unite dou cte dou printr-o muchie.
Graful se reprezint n plan prin intermediul unor elemente geometrice: nodurile se
reprezint prin cercuri, iar muchiile prin linii drepte anumite cercuri.

Elementele mulimii X (nodurile) se identific cu ajutorul unor etichete, care pot fi
numere sau litere. Pentru simplificare, vom folosi ca etichete un ir de numere
consecutive, ncepnd cu numrul 1. De exemplu, pentru un graf cu n noduri, vom folosi
etichetele: 1, 2, 3, ...,n-1, n. O muchie se va nota cu [i,j], unde i i j sunt etichetele
nodurilor incidente cu muchia. De exemplu, muchia [2,3] este muchia care unete
nodurile cu etichetele 2 i 3.
Exemplul 1:
n graful G
1
=(X
1
,U
1
) din figura 1:
Ordinul grafului este 8.
Graful are 8 noduri (n=8) i mulimea nodurilor este X
1
={1, 2, 3, 4, 5, 6, 7, 8}.
Graful are 9 muchii (m=9) i mulimea muchiilor este
U
1
={[1,2], [1,3], [1,4], [2,3], [2,5], [3,4], [3,5], [6,7], [6,8]}.
Nodul 1 este nod adiacent cu nodurile 2, 3 i 4, iar nodul 6 este adiacent cu nodurile 7
i 8. Nodurile 3 i 4 sunt adiacente deoarece perechea de noduri [3,4]U
1
. Nodurile 5 i 6
nu sunt adiacente deoarece perechea de noduri [5,6] U
1
. Nodul 5 este nod incident
cu muchiile [2,5] i [3,5], dar nu este incident cu muchia [1,2].
Nodul 3 este nod extrem muchiilor [1,3], [2,3], [3,4] i [3,5].
Muchiile [1,2] i [2,3] sunt muchii incidente deoarece au un nod comun (nodul 2).
Muchiile [1,4] i [2,3] nu sunt muchii incidente deoarece nu au un nod comun.

Dac graful neorientat G are n noduri (x
1
, x
2
, ..., x
n
), atunci numrul total de grafuri
neorientate care se pot forma cu aceste noduri este g:
g=
2
2
n
C

Gradul unui nod al grafului neorientat
Nodul x
i

Nodul x
j

Muchia u
k
= [x
i
, x]

Nodul unui graf este caracterizat prin grad.Gradul unui nod x
k
al grafului G este egal cu
numrul muchiilor incidente cu nodul i se noteaz cu d(x
k
).Se numete nod terminal un
nod care are gradul egal cu 1 : d(x
k
) = 1 (este incident cu o singur muchie).Se numete
nod izolat un nod care are gradul egal cu 0 : d(x
k
) = 0 (nu este adiacent cu nici un alt nod
al grafului, adic nu se gsete n extremitatea nici unei muchii).
Exemplul 1:
Graful G
4
=(X
4
,U
4
) din figura 4 este definit astfel: X
4
={1,2,34,5,6,7,8,9,10,11}
U
4
={[1,2], [1,4], [2,3], [2,5], [3,4], [3,5], [5,6], [5,7], [5,8] [7,9]}. n graful G
4
:
Gradul nodului 5 este 5, deoarece are 5 muchii incidente: [2,5], [3,5], [5,6], [5,7] i
[5,8].
Nodul 9 este nod terminal, deoarece are gradul 1 (o singur muchie incident: [7,9]).
Nodul 10 este nod izolat, deoarece are gradul 0 (nicio muchie incident).


Fig.4 Graful G
4


ntr-un graf cu n noduri, oricare ar fi nodul x
k
, gradul su este mai mare sau egal cu 0 i
mai mic sau egal cu n-1 (0 d(x
k
) n-1).Dac graful G are m muchii (u
1
, u
2
,. ., u
m
) i n
noduri (x
1
, x
2
,.... x
n
), atunci ntre gradul nodurilor i numrul de muchii exist urmtoarea
relaie: suma gradelor tuturor nodurilor grafului este egal cu dublul numrului de
muchii:

=
n
i
i
x d
1
( )=2m

Exemplul 2 :
n graful G
4
: d(1) + d(2) + d(3) + d(4) + d(5) + d(6) + d(7) + d(8) + d(9) + d(10) + d(11)
= 2+2+3+2+4+1 +2+1+1+0+0 = 18 = 2*9 = 2*m

Numrul minim de muchii, m
min
, pe care trebuie s le aib un graf neorientat, cu n
noduri, ca s nu existe noduri izolate, este:
m
min
=
(

+
2
1 n

Dac graful G are n noduri (n 2), atunci cel puin dou noduri au acelai grad.

1
4
2
3 7 5 9
8
6 10
11
I.1.2. Graful orientat
Elementele mulimii U (perechile de noduri)se numesc arce.Mulimea U se mai numete
i mulimea arcelor grafului G.Un arc,fiind un element din mulimea U,este determinat
de o submulime ordonat,cu dou elemente,din mulimea X:arcul k al grafului(u
k
),ce
unete nodurile x
i
i x
j
,este determinat de submulimea {x
i
,x
j
}i se noteaz cu
[x
i
,x
j
].[x
i
,x
j
] i [x
j
,x
i
]nu reprezint acelai arc al grafului.Graful G are m arce: numrul
de arce=card(U)=m.
Se numesc noduri adiacente n graful G oricare din perechile de noduri care formeaz
un arc (x
i
,x
j
)U sau(x
j
,x
i
)U.Fiecare dintre cele dou noduri (x
i
i x
j
) este nod incident cu
arcul u
k
=[x
i
,x
j
] sau cu arcul u
k
=[x
j
,x
i
].
Nodurile x
i
si x
j
sunt extremitile arcului [x
i
,x
j
].Nodul x
i
este extremitatea iniial a
arcului,iar nodul x
j
este extremitatea final a arcului.Se numesc arce incidente dou arce
u
i
i u
j
care au o extremitate comun nodul x
k
.
Se numete successor al nodului x
i
orice nod la care ajunge un arc care iese din nodul
x
j
.Mulimea succesorilor nodului x
i
este format din mulimea nodurilor la care ajung
arcele care ies din nodul x
j
.Se noteaz cu S(x
i
) i se definete ca mulimea:
S(x)={x
j
X|(x
i
,x
j
)U}.
Se numete predecesor al nodului x
i
orice nod de la care intr un arc n nodul
x
j
.Mulimea predecesorilor nodului x
i
este format din mulimea nodurilor de la care
ajung arcele care intr in nodul x
i
.Se noteaz cu P(x
i
) i se definete ca mulimea:
P(x)={x
j
X|(x
j
,x
i
)U}.
Mulimea arcelor care ies din nodul x
i
se noteaz cu U
+
(x
i
) i se definete ca mulimea
U
+
(x
i
)={u=(x
i
,x
j
)|u U}.
Mulimea arcelor care intr in nodul x
i
se noteaz cu U
-
(x
i
) i se definete ca mulimea
U
-
(x
i
)={u=(x
j
,x
i
)| u U}.
Nodul surs al grafului este nodul care are mulimea succesorilor format din toate
celelalte noduri,mai puin el,iar mulimea predecesorilor si este mulimea vid.
Nodul destinaie al grafului este nodul care are mulimea predecesorilor format din
toate celelalte noduri,mai puin el,iar mulimea succesorilor si este mulimea vid.
Spre deosebire de graful neorientat,n graful orientat perechile de noduri sunt
ordonate.Graful orientat se mai numete i digraf.
Observaii:
1.card(s(x))=card(U
+
(x)) si card(P(x))=card(U
-
(x)).
2.Pentru nodul surs al grafului card(S(x))=card(X)-1 si card(P(x))=0.
3.Pentru nodul destinaie al grafului card(P(x))=card(X)-1 si card(S(x))=0.
4.Dac un graf are un nod surs,atunci nu poate avea un nod destinaie,i invers.
Un graf orientat G este definit de o pereche de mulimi : mulimea nodurilor sale X i
mulimea arcelor sale U.El poate fi considerat ca o mulime de noduri din care unele
pot fi unite dou cate dou,prin unul sau dou arce.
Graful orientat se reprezint n plan prin intermediul unor elemente
geometrice:nodurile se reprezint prin cercuri,iar arcele prin linii drepte care unesc
anumite cercuri i care au o sgeat la captul care corespunde extremitii finale a
arcului.

Nodul x
i
al grafului G

Arcul u
k
=[x
i
,x
j
]al grafului G
Nodul x
j
al grafului G

Dac graful orientat G are n noduri(x
1
,x
2
,...,x
n
),atunci numrul total de grafuri
orientate care se pot forma cu aceste noduri este g:
g=4
nx(n-1)/2
Gradele unui nod al grafului orientat

Nodul unui graf orientat este caracterizat prin gradul intern i gradul extern.
Gradul intern al unui nod x
i
al grafului G este egal cu numrul arcelor care intr n nodul
x
i
(arce de forma [x
i
,x
j
] i se noteaz cu d
-
(x).
Gradul extern al unui nod x
i
al grafului G este egal cu numrul arcelor care ies din nodul
x
i
(arce de forma [x
i
,x
j
] i se noteaz cu d
+
(x)
Se numete nod terminal un nod care are suma gradelor egal cu 1 (gradul intern sau
gradul extern egal cu 1 i gradul extern,respectiv gradul intern, egal cu 0 - d
+
(x
k
) =1 i
d
-
(x
k
)=0 sau d
-
(x
k
)=1 i d
+
(x
k
)=0).Nodul terminal este incident cu un singur arc.
Se numete nod izolat un nod care are suma gradelor egal cu 0(gradul intern i gradul
extern egale cu 0- d
+
(x
k
) =d
-
(x
k
) =0).Nodul izolat nu este adiacent cu nici un alt nod al
grafului,adic nu se gasete la extremitatea nici unui arc.
Observaii:
1.d
+
(x)=card(S(x)) i d
-
(x)=card(P(x)).
2.Dac graful are n noduri, pentru un nod surs al grafului d
+
(x)=n-1 i d
-
(x)=0, iar
pentru un nod destinaie al grafului d
-
(x)=n-1 i d
+
(x)=0.
Exemplul 1:
Fie grafurile G
12
=(X
12
,U
12
) ,unde X
12
={1,2,3,4} i
U
12
={[1,2],[1,3],[1,4],[2,3],[3,4],[4,3]}, i G
13
=(X
13
,U
13
),unde X
13
={1,2,3,4} i
U
13
={[2,1],[2,3],[3,1],[3,4],[4,1],[4,3]}.
Din lista muchiilor unui graf, se pot preciza urmtoarele informaii:
o nodul surs al unui graf apare pe primul loc din pereche de n-1 ori - i
niciodat pe locul al doilea.n graful G
12
nodul 1 este nod surs.
o nodul destinaie al unui graf apare pe al doilea loc din pereche de n-1 ori i
niciodat pe primul loc.n graful G
12
nodul 1 este nod destinaie.
ntr-un graf cu n noduri, oricare ar fi nodul x
k
, oricare dintre gradele sale este mai mare
sau egal cu 0 i mai mic sau egal cu n-1(0 d
+
(x
k
) n-1 i 0 d
-
(x
k
) n-1).
Dac graful orientat G are m arce (u
1
,u
2
,u
m
) i n noduri(x
1
,x
2
,x
n
), atunci ntre
gradele nodurilor i numrul de muchii exist urmtoarea relaie:suma gradelor interne
ale tuturor nodurilor este egal cu suma gradelor externe ale tuturor nodurilor i cu
numrul de arce.
( ) ( )
i
1
-
i
1
x d x d

= =
+
=
n
i
n
i

I.2. Reprezentarea i implementarea grafului
Exist mai multe moduri de reprezentare la nivel logic a unui graf,care pot fi
implementate n memoria unui calculator,folosind diverse tipuri de structuri de
date.Aceste reprezentri pot fi folosite n algoritmii care prelucreaz grafuri i,implicit,n
programele prin care vor fi implementai n calculator aceti algoritmi.Printre modurile de
reprezentare a unui graf se numr
- reprezentarea prin matricea de adiacen;
- reprezentarea prin matricea de inciden;
- reprezentarea prin lista muchiilor(arcelor);
- reprezentarea prin lista de adiacen(listele vecinilor);
- reprezentarea prin matricea costurilor.
Fiecare reprezentare prezint avantaje n ceea ce privete utilizarea eficient a memoriei
interne,n funcie de tipul grafului(cu noduri puine,dar cu muchii multe-sau cu noduri
multe,dar cu muchii puine) i din punct de vedere al eficienei algoritmilor de prelucrare
(n funcie de aplicaie).n urmtoarele reprezentri se consider c graful G=(X,U) are n
noduri i m muchii.

I.2.1.Reprezentarea prin matricea de adiacen
Matricea de adiacen a unui graf este o matrice ptrat binar de ordinul n(A
n,n
),ale
crei elemente a
i,I
sunt definite astfel:

A
ij
= 1, dac [i,j] e U
0, dac [i,j] e U
Implementarea grafului prin matricea de adiacen se face printr- un tablou
bidimensional (o matrice ptrat cu dimensiunea n),astfel:
int a[<n>][<n>];
Exemplul 1:


1 2 3 4 5 6 7 8
0 1 1 1 0 0 0 0
1 0 1 0 1 0 0 0
1 1 0 1 1 0 0 0
1 0 1 0 0 0 0 0
0 1 1 0 0 0 0 0
0 0 0 0 0 0 1 1
0 0 0 0 0 1 0 0
0 0 0 0 0 1 0 0

Proprietile matricei de adiacen:
1.Elementele de pe diagonala principal au valoarea 0 -din definiia grafului rezult c
orice muchie(arc) [i,j] trebuie s respecte condiia ij.
2.n cazul unui graf neorientat,matricea de adiacen este o matrice simetric fat de
diagonala principal,deoarece,dac exist muchia [i,j],atunci exist i muchia[j,i].
Aceast reprezentare este recomandat pentru problemele n care se testeaz prezena
unei muchii sau a unui arc ntre dou noduri,se calculeaz gradul unui nod etc.-deoarece
permite un acces rapid la nodurile i muchiile(arcele) unui graf.

Algoritmi pentru reprezentarea grafurilor folosind matricea de adiacen
Din matricea de adiacen putei obine urmtoarele informaii:
Graf neorientat Graf orientat
Suma elementelor matricei de adiacen
este egal cu 2xm(dublul numrului de
muchii).
Suma elementelor matricei de adiacen
este egal cu m(numrul de arce).
Nodurile adiacente nodului i sunt nodurile j
(j=1,n) pentru care elementele din linia i
sunt egale cu 1(a[i,j]=1).Mai pot fi definite
ca nodurile j(j=1,n) pentru care elementele
din coloana i sunt egale cu 1 (a[j,i]=1).
Succesorii nodului i sunt nodurile j(j=1,n)
pentru care elementele din linia i sunt egale
cu 1 (a[i,j]=1).
Predecesorii nodului i sunt nodurile
j(j=1,n) pentru care elementele din coloana
i sunt egale cu 1 (a[j,i]=1).
Nodurile adiacente nodului i sunt nodurile
j (j=1,n) pentru care elementele din linia i
sau din coloana i sunt egale cu 1 (a[i][j]=1
sau a[j][i]=1 reuniunea dintre mulimea
succesorilor si mulimea predecesorilor
nodului.
Numrul de vecini ai nodului i este egal cu
gradul nodului.
Numrul de vecini ai nodului i este egal cu
cardinalul mulimii de noduri adiacente
nodului i.
Muchia [i,j] a grafului reprezint un
element al matricei de adiacen care
Arcul [i,j] al grafului reprezint un element
al matricei de adiacen care indeplinete
indeplinete condiia : a[i][j]=1 (sau
a[j][i]=1).
condiia: a[i][j]=1.

Implementarea algoritmilor pentru reprezentarea grafurilor cu matricea de
adiacen.
1.Crearea matricei de adiacen prin introducerea datelor de la tastatur.Determinarea
gradului unui nod .Salvarea matricei de adiacen ntr-un fiier text.
Se citesc de la tastatur muchiile (arcele) unui graf orientat (neorientat),se creeaz
matricea de adiacen a grafului ,se afieaz nodurile izolate i terminale i se salveaz
matricea de adiacen n fiierul text graf1.txt, pentru graful neorientat i graf2.txt,pentru
graful orientat .n fiierul text se scriu, pe primul rnd, ordinul grafului, i pe urmtoarele
rnduri, liniile matricei de adiacen Funcia scrie() se folosete pentru a scrie matricea de
adiacen n fiier.Deoarece matricea de adiacen a fost declarat ca variabil global,
elementele ei sunt iniializate cu valoarea 0.
Graful neorientat. n programul 1, funcia grad() se folosete pentru a determina gradul
unui nod.
Programul 1
#include<fstream.h>
int a[10][10],n,m;
fstream f(graf1.txt,ios::out);
void scrie()
{int i,j; f<<n<<endl;
for(i=1 ;i<=1;i++) {for (j=1;j<=1;j++) f<<a[i][j]<< ; f<<endl;}
f .close();}
int grad (int i)
{int j,g=0;
for (j=1;j<=n;j++) g
+
=a[i][j]; return g;}
void main()
{int i,j,k;
Cout<<numar de noduri ; cin>>n; cout<<numar de muchii ; cin>>m;
for(k=1;k<=m;k++)
{cout<<primul nod al muchiei <<k<<: ; cin>>i;
cout<<al doilea nod al muchiei <<k<<: ; cin>>j;
a[i][j]=1; a[j][i]=1;}
cout<<Nodurile izolate sunt: ;
for(i=1;i<=n;i++) if(grad(i)==0) cout<<i<< ;
cout<<endl<<Nodurile terminale sunt: ;
for(i=1;i<=n;i++) if (grad(i)==1) cout<<i<< ;
scrie();}
Graful orientat.n programul 2,funcia grad_int() se folosete pentru a determina gradul
intern al unui nod, iar funcia grad_ext() se folosete pentru a determina gradul extern al
unui nod
Programul 2
#include<fstream.h>
int a[10][10],n,m;
fstream f(graf2.txt,ios::out);
void scrie() {//este identic cu cea de la graful neorientat}
{int grad ext(int i.)
{int j,g=0;
for (j=1;j<=n;j++) g
+
=a[i][j]; return g;}
int grad_int(int i)
{int j,g=0;
for (j=1;j<=n;j++) g
+
=a[j][i]; return g;}
void main()
cout<<numar de noduri ; cin>>n; cout<<numar de arce ; cin>>m;
for(k=1;k<=m;k++)
{cout<<nodul initial al arcului <<k<< : ; cin>>i;
cout<<nodul final al arcului <<k<< : ;cin>>j; a[i][j]=1;}
cout<<Nodurile izolate sunt: ;
for (i=1;i<=n;i++) if(grad_int(i)+grad_ext(i)==0) cout<<i<< ;
cout<<endl<<Nodurile terminale sunt: ;
for (i=1;i<=n;i++) if (grad_int (i)+grad_ext(i)==1) cout<<i<< ;
scrie();}

2.Crearea matricei de adiacen prin citirea datelor din fiier.Determinarea numrului
de vecini ai unui nod.Afiarea muchiilor(arcelor)grafului.
Se citesc din fiierele text create anterior matricele de adiacen ale celor dou grafuri-
graf1.txt,respectiv graf2.txt.Se afieaz nodurile care au cei mai muli vecini (cele mai
multe noduri adiacente).Se determin numrul de muchii(arce) ale grafului i se afieaz
muchiile(arcele).Funcia citete() se folosete pentru a citi matricea de adiacen din
fiier.
Graful neorientat. n programul 3,funcia nr_m() se folosete pentru a determina
numrul de muchii ale grafului.La afiarea muchiilor,pentru a nu se afia de dou ori
aceeai muchie,se parcurge matricea de adiacen numai deasupra diagonalei principale.
Programul 3
#include<fstream.h>
int a[10][10],n;
fstream f(graf1.txt,ios::in);
void citeste()
{int i,j; f>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) f>>a[i][j]; f.close();}
int nr_m()
{int i,j,m=0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) m
+
=a[i][j]; return m/2;}
int grad(int i) {//este identic cu cea de la exemplul anterior}
void main()
{int i,j,max; citeste(); max=grad(1);
for(i=2;i<=n;i++) if (grad(i)>max) max=grad(i);
cout<<Nodurile cu cei mai multi vecini sunt: ;
for(i=1;i<=n;i++) if (grad(i)==max) cout<<i<< ;
cout<<endl<<graful are<<nr m()<<muchii <<endl;
cout<<Muchiile grafului sunt: ;
for(i=1;i<=n;i++)
for(j=i+1;j<=n;j++) if (a [i][j]==1; cout<<i<<-<<j<< ;}
Graful orientat.n programul 4,funcia nr_a() se folosete pentru a determina numrul
de arce ale grafului.Funcia vecini() se folosete pentru a determina numrul de vecini al
unui nod.La afiarea arcelor,se parcurge toat matricea de adiacen.
Programul 4
#include<fstream.h>
int a[10][10],n;
fstream f(graf2.txt,ios::in);
void citeste() {//este identic cu cea de la graful neorientat}
int nr_a()
{int i,j,m=0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) m
+
=a[i][j]; return m;}
int vecini(int i)
{int j,v=0;
for (j=1;j<=n;j++) if (a[i][j]==1|| a[j][i]==1) v++; return v;}
void main()
{int I,j,max; citeste(); max=vecini(1);
for(i=2;i<=n;i++) if(vecini(i)>max) max=vecini(i);
cout<<Nodurile cu cei mai multi vecini sunt: ;
for(i=1;i<=n;i++) if (vecini(i)==max) cout<<i<< ;
cout<<endl<<Graful are<<nr_a()<<arce<<endl;
cout<<Arcele grafului sunt: ;
for(i=1;i<=n;i++) for(j=i+1;j<=n;j++) if (a [i][j]==1; cout<<i<<-<<j<< ;}

3.Crearea matricei de adiacen prin citirea muchiilor(arcelor )din fiier.Determinarea
vecinilor unui nod.
n programele 5 i 6, datele se citesc din fiierul text graf3.txt,pentru graful neorientat,i
graf4.txt,pentru graful orientat.n fiier sunt scrise,pe primul rnd,desprite prin
spaii,numrul de noduri i numrul de muchii(arce) ale grafului,i apoi pe cte un
rnd,separate prin spaiu,cele dou noduri terminale ale fiecrei muchii(arc).Se afieaz
vecinii fiecrui nod.Funcia citete() se folosete pentru a citi datele din fiier,iar funcia
vecini() pentru a determina vecinii unui nod.Fiierele text se creeaz cu ajutorul unui
editor de texte.
Graful neorientat.-Programul 5
#include<fstream.h>
int a[10][10],n,m;
fstream f(graf3.txt,ios::in);
void citeste()
{int k,i,j; f>>n>>m;
for(k=1;k<=m;k++) {f>>i>>j; a[i][j]=1; a[j][i]=1;} f.close();}
void vecini(int i)
{for(int j=1;j<=n;j++) if (a[i][j]==1) cout<<j<< ;}
void main()
{int i; citeste(); cout<<Vecinii fiecarui nod sunt: <<endl;
for(i=1;i<=n;i++) {cout<<Nodul<<i<< ; vecini(i); cout<<endl;}}
Graful orientat-Programul 6
#include<fstream.h>
int a[10][10],n,m;
fstream f(graf3.txt,ios::in);
void citeste()
{int k,i,j; f>>n>>m;
for(k=1;k<=m;k++) {f>>i>>j; a[i][j]=1; a[j][i]=1;} f.close();}
void vecini(int i)
{for(int j=1;j<=n;j++) if (a[i][j]==1|| a[j][i]==1) cout<<j<< ;}
void main()
{int i; citeste(); cout<<Vecinii fiecarui nod sunt: <<endl;
for(i=1;i<=n;i++) {cout<<Nodul<<i<< ; vecini(i); cout<<endl;}}

4.Generarea matricei de adiacen.
Pentru a testa programele care prelucreaz grafuri implementate cu matricea de
adiacen, se pot genera aleatoriu matricea de adiacen.n programul 7,funcia
generare() genereaz matricea de adiacen a unui graf neorientat,cu n noduri i m
muchii.
Programul 7
#include<iostream.h>
#include<stdlib.h>
int a[10][10],n,m;
void generare()
{int k=0,i,j; randomize();
while(k<m)
{i=rand() %n+1; j=rand()%n+1;
if(i!=j && a[i][j]==0) {a[i][j]=1; a[j][i]=1; k++;}}}
void main()
{cout<<n= ; cin>>n; cout<<m= ; cin>>m;
while(m>n
*
(n-1)/2} {cout<<m= ; cin>>m;}
generare(); }







II.2.2. Reprezentarea prin matricea de inciden
Matricea de inciden a unui graf neorientat este o matrice binar cu n linii i m coloane
(A
n,m
), ale crei elemente a
i,j
sunt definite astfel:
a
i,j
= 1, dac [i,j] U
0, dac [i,j] U
Implementarea grafului neorientat prin matricea de inciden se face printr-un tablou
bidimensional (o matrice cu dimensiunea n
m),astfel:
int a[<n>][<m>];








Proprietaile matricei de inciden a grafului neorientat:
1.Pe fiecare coloan exist dou elemente cu valoarea 1 (pe liniile i i j care corespund
nodurilor incidente cu muchia),iar restul elementelor au valoarea 0.
2.Matricea de inciden are 2xm elemente egale cu 1, deoarece fiecare muchie este
incident cu dou noduri.
Matricea de inciden a unui graf orientat este o matrice cu n linii i m coloane
(A
n,m
),ale crei elemente a
i,j
sunt definite astfel:
1, dac nodul i este extremitatea final a arcului j
a
i,j
= -1,dac nodul i este extremitatea iniial a arcului j
0,dac nodul i nu este extremitate a arcului j
Implementarea grafului orientat prin matricea de inciden se face printr-un tablou
bidimensional (o matrice cu dimensiunea nxm),astfel:
int a[<n>][<m>]

1 1 1 0 0 0 0 0 0
1 0 0 1 1 0 0 0 0
0 1 0 1 0 1 1 0 0
0 0 1 0 0 1 0 0 0
0 0 0 0 1 0 1 0 0
0 0 0 0 0 0 0 1 1
0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 1
2 1
5
8
U
1
U
5
U
2
U
4
3
U
8
U
9
6
4
7
Graful G
1

U
6
U
7
U
3










Matricea de inciden este:






Proprietile matricei de inciden a grafului orientat:
1. Pe fiecare coloan exist un element cu valoarea 1 (pe linia i care corespunde
extremitii finale a arcului) i un element cu valoarea -1 (pe linia j care corespunde
extremittii iniiale a arcului),iar restul elementelor au valoarea 0.
2.Matricea de inciden are m elemente egale cu 1i m elemente egele cu -1, deoarece
fiecare arc are o extremitate iniial i o extremitate final.
Suma elementelor matricii este 0.
Aceast reprezentare este recomandat pentru grafurile care au un numr mare de noduri
i un mumr mic de muchii.

Algoritmi pentru reprezentarea grafurilor folosind matricea de inciden.
Din matricea de inciden putei obine urmtoarele informaii:
1 -1 0 0 0 0 0 0 0 0
-1 1 -1 -1 1 0 0 0 0 0
0 0 1 0 0 1 -1 0 0 0
0 0 0 1 -1 0 0 -1 0 0
0 0 0 0 0 -1 1 1 1 -1
0 0 0 0 0 0 0 0 1 -1
Graf neorientat Graf orientat
Graful orientat G
9
1 2 3
4 5 6
U
2
U
1
U
3
3
U
5
U
8
U
7
U
9
U
10
U
4
U
6

Implementarea algoritmilor pentru reprezentarea grafurilor cu matricea de
inciden
1.Crearea matricei de inciden prin introducerea datelor de la tastatur.Determinarea
gradului unui nod .Salvarea matricei de inciden ntr-un fisier text.
Se citesc de la tastatur muchiile(arcele)unui graf orientat(neorientat).Se creaz matricea
de inciden a grafului.Se afieaz gradul nodului p a crui etichet se introduce de la
tastatur.Se salveaz matricea de inciden n fiierul graf5.txt , pentru graful neorientat i
graf6.txt pentru graful orientat.n fiierul text se scriu pe primul rnd ordinal grafului i
numarul de muchii,iar pe urmtoarele rnduri,liniile matricei de inciden.Funcia scrie( )
se folosete pentru a scrie matrice de inciden n fiier.
Graful neorientat .n programul 1,funcia grad( )se folosete pentru a determina gradul
unui nod.
Programul 1
#include <fstream.h>
int a[10][10],n,m;
fstream f(graf5.txt,ios::out);
void scrie( )
Gradul unui nod i este egal cu suma
elementelor de pe linia i
Gradul intern al unui nod i este egal cu
numrul de elemente cu valoare 1 de pe
linia i. Gradul extern al unui nod i este egal
cu numrul de elemente cu valoarea -1 de
pe linia i
Nodurile adiacente nodului i sunt nodurile
j(j=1,n )pentru care elementele din linia j
sunt egele cu 1 n coloana k (k=1,m) n
care i elemente de pe linia i au valoarea 1:
a[i][k]=1 i a[j][k]=1
Succesorii nodului i sunt nodurile j (j=1,n)
pentru care elementele din linia j sunt
egale cu 1 n coloana k (k=1,m) n care
elementele de pe linia i au valoarea -
1:a[i][k]= -1 i a[j][k]=1.
Predecesorii nodului i sunt nodurile
j(j=1,n) pentru care elementele din linia j
sunt egale cu -1 n coloana k (k=1,m) n
care elementele de pe linia i au valoarea 1:
a[i][k]=1 i a[j][k]= -1
Nodurile adiacente nodului i sunt date de
reuniunea dintre mulimea succesorilor i
mulimea predecesorilor nodului.
Numrul de vecini ai nodului i este egal cu
gradul nodului.
Numrul de vecini ai nodului i este egal cu
cardinalul mulimii de noduri adiacente
nodului i
Muchia k=[i,j] a grafului este determinat
de dou elemente ale matriceii a[i]kj] i
a[j]kj],care ndeplinesc condiia a[i][k]=1
i a[j][k]=1 i semnific faptul c
muchia k este incident cu nodurile i i j
Arcul k=[i,j] al grafului este determinat de
dou elemente ale matricei ,a[i]kj] i
a[j]ki],care ndeplinesc condiia a[i][k]=-1
i a[j][k]=1 i semnific faptul c arcul k
iese din nodul i i intr n nodul j
{ int i,j; f<<n<< <<m<<endl;
for (i=1; i<=n; i++)
{ for (k=1 ; k<=m; k++)
f<<a[i] [k]<< ; f<<endl;}
f.close( ); }
int grad (int i)
{ int g=0,k;
for (k=1 ; k<=m; k++)g+=a[i] [k]; return g;}
void main ( )

{ int i,j,p,k;
cout<<numr de moduri; cin>>n;
cout<<numr de muchii; cin>>m;
for ( k=1; k<=m; k++)
{ cout<<primul nod al muchiei<<k<<: ; cin>>i;
cout<<al doilea nod al muchiei <<k<< : ; cin>>j;
a[i][k]=1; a[j][k]=1; }
cout<<nodul= ; cin>>p;
cout<<Gradul nodului <<p<< este <<grad (p)<<endl;
scrie ( ) ;}
Graful orientat. In programul 2,funcia grad_int( ) se folosete pentru a determina
gradul intern al unui nod , iar funcia grad_ext ( ) se folosete pentru a determina
gradul extern al unui nod.
Programul 2
#include<fstream.h>
int a [10][10],n,m;
fstream f (graf6.txt,ios: :out ) ;
int scrie( )
{ int i,j; f<<n<< <<m<<endl;
for (i=1; i<=n; i++)
{ for (k=1 ; k<=m; k++)
f<<a[i] [k]<< ; f<<endl;}
f.close( ); }
int grad_int (int i)
{ int g=0,k;
for (k=1; k<=m; k++)if (a[i][k]==1) g++; return g; }
int grad_ext (int i)
{int g=0,k;
for (k=1; k<=m; k++)if (a[i][k] == -1) g++ ; return g: }
void main ( )
{ int i,j,p,k;
cout<<numr de noduri; cin>>n;
cout<<numr de muchii; cin>>m;
for (k=1; k<=m ; k++)
{ cout<<nodul iniial al arcului <<k<< : ; cin>>i;
cout<<nodul final al arcului <<k<< : ; cin>>j;
a[i][k]=-1; a[j][k]=1; }
cout<<nodul= ; cin>>p;
cout<<Gradul intern al nodului <<p<< este <<grad_int (p)<<endl;
cout<<Gradul extern al nodului <<p<< este <<grad_ext (p)<<endl;
scrie( ) ; }

2.Crearea matricei de inciden prin citirea datelor din fiier.Afiarea vecinilor unui
nod.
Se citesc din fiierele create anterior (graf5.txt,graf6.txt) matricele de inciden ale
celor dou grafuri i se afieaz vecinii unui nod x a crui etichet se introduce de la
tastatur. Funcia
citete ( ) se folosete pentru a citi matricea de inciden din fiier
Graf neorientat. n programul 3,funcia vecini( ) se folosete pentru a determina vecinii
unui nod.


Programul 3
#include<fstream.h>
int a [10][10],n,m;
fstream f (graf5.txt,ios: :in ) ;
void citete( )
{ int i,k ; f>>n>>m;
for (i=1; i<=n; i++)
for (k=1;k<=m; k++) f>>a[i] [k]; f.close( ); }
void vecini (int i)
{ int k,j;
for (k=1;k<=m; k++)
if (a[i] [k] = =1)
for (j=1 ; j<=n ; j++)
if (j!=0 && a[j][k]= =1)
cout<<j<< ;}
void main( )
{int p;
cout<<nodul= ; cin>>x; citete ( );
cout<<vecinii nodului<<x<<sunt nodurile;
vecinii(x);}
Graf orientat.
n programul 4,vectorii binari s i p se folosesc pentru a memora succesorii, respectiv
predecesorii nodului x.Elementul i are valoarea 1dac nodul i este succesor,respectiv
predecesor al nodului x;altfel are valoarea 0.Funciile succ( ) i pred( ) se folosesc pentru
a determina n vectorii s i p succesorii,respective predecesorii unui nod.Funcia vecini( )
se folosete pentru a determina vecinii unui nod,prin reuniunea mulimii predecesorilor
i succesorilor.
Programul 4
#include<fstream.h>
int a [10][10],n,m,s[10],p[10];
fstream f (graf6.txt,ios: :in ) ;
void citete( )
{ int i,k ; f>>n>>m;
for (i=1; i<=n; i++)
for (k=1;k<=m; k++) f>>a[i] [k]; f.close( ); }
void succ(int i)
{ for (int k=1; k<=m; k++)if (a[i] [k] = =-1)
for (int j=1 ; j<=n ; j++) if (j!=i && a[j][k]= =1) s[j]=1;}
void pred (int i)
{ for (int k=1; k<=m; k++)if (a[i] [k] = =1)
for (int j=1 ; j<=n ; j++)
if (j!=i && a[j][k]= =-1) p[j]=1;}
void vecini (int i)
{ int j; succ(i); pred(i);
for (j=1;j<=n; j++)
if (j!=i && (s[j]==1 | |p[j]==1))
cout<<j<< ;}
void main( )
{int x;
cout<<nodul= ; cin>>x; citete ( );
cout<<vecinii nodului<<x<<sunt nodurile;
vecinii(x);}

3.Crearea matricei de inciden prin citirea muchiilor (arcelor) din fiier.Prelucrarea
informaiilor asociate muchiilor.
n programele 5 i 6, datele se citesc din fiierul text graf7.txt pentru graful neorientat,i
graf8.txt pentru graful orientat.n fiier sunt scrise,pe primul rnd desprite prin
spaii,numrul de noduri i numrul de muchii(arce) ale grafului i apoi,pe cte un
rnd,separate prin spaiu,cele dou noduri terminale ale fiecrei muchii(arc) i lungimea
muchiei (arcului).Se afieaz muchiile(arcele) care au lungimea mai mare dect lungimea
medie a muchiilor(arcelor) din graf.Se folosete vectorul d pentru a memora lungimea
fiecrei muchii(arc).Funcia citete( ) se folosete pentru a citi datele din fiier,funcia
medie( ) pentru a determina lungimea medie a muchiilor(arcelor)din graf iar funcia
afiare( ) pentru a afia muchiile(arcele) care au lungimea mai mare dect media.Fiierele
text se creaz cu ajutorul unui editor de texte.n aceste grafuri se asociaz fiecrei
muchii(arc) o valoare pentru lungime.
Graf neorientat=-Programul 5
#include<fstream.h>
int a [10][10],d[10],n,m;
fstream f (graf7.txt,ios: :in ) ;
void citete( )
{ int i,j,l,k ; f>>n>>m;
for (k=1;k<=m; k++)
{ f>>i>>j>>l; a[i][k]=1; a[j][k]=1; d[k]=1;} f.close( ); }
float media( )
{ int i,s=0;
for (i=1;i<=m;i++)s+=d[i];return (float)s/m;}
void afieaz( )
{int i,k;
float dm=media( );
for (k=1;k<=m; k++)
if(d[k]>dm)
{for (i=1;i<=n;i++)
if(a[i][k]==1) cout<<i<< ;
cout<<cu lungimea<<d[k]<<endl;}}
void main( )
{ citete ( );
cout<<media lungimii este:<<media( )<<endl;
cout<<muchiile sunt<<endl;
afieaz( );}
Graf orientat-Programul 6
#include<fstream.h>
int a [10][15],d[15],n,m;
fstream f (graf8.txt,ios: :in ) ;
void citete( )
{ int i,j,l,k ; f>>n>>m;
for (k=1;k<=m; k++)
{ f>>i>>j>>l; a[i][k]=-1; a[j][k]=1; d[k]=1;} f.close( ); }
float media( )
{ int i,s=0;
for (i=1;i<=m;i++)s+=d[i];return (float)s/m;}
void afieaz( )
{int i,k,x,y;
float dm=media( );
for (k=1;k<=m; k++)
if(d[k]>dm)
{for (i=1;i<=n;i++)
{if(a[i][k]==-1) x=i; if(a[i][k]==1) y=i;}
cout<<x<<-<<y<<cu lungimea<<d[k]<<endl;}}
void main( )
{ citete ( );
cout<<media lungimii este:<<media( )<<endl;
cout<<arcele sunt:<<endl;
afieaz( );}
4.Crearea matricei de inciden prin citirea datelor din matricea de adiacen.Afiarea
muchiilor i a nodurilor izolate.
n programele 7 i 8, matricele de adiacen se citesc din fiierele text create anerior
:graf1.txt pentru graful neorientat i graf2.txt pentru graful orientat.Se ceeaz matricele
de inciden ale celor dou grafuri,se afieaz muchiile(arcele) i nodurile izolate.Se
salveaz n fiierul text graf9.txt respectiv graf10.txt.informaiile despre muchii,astfel:pe
primul rnd ,desprite prin spaii,numrul de noduri i numrul de muchii(arce) ale
grafului i apoi,pe cte un rnd,separate prin spaiu,cele dou noduri terminale ale
fiecrei muchii(arc).Se folosesc matricele a pentru matricea de adiacen i b pentru
matricea de inciden i funciile citete() pentru a citi matricea de adiacen din
fiier,salveaz()pentru a salva n fiierul text informaiile despre muchiile(arcele)
grafului, transform() pentru a obine matricea de inciden din matricea de adiacen,
afieaz_noduri_izolate() pentu a afia nodurile izolate i afieaz_muchii( ) pentru a
afia muchiile (arcele).
Graful neorientat-Programul 7
#include<fstream.h>
int a [10][10],n,m,b[10][20];
fstream f 1(graf1.txt,ios: :in ) ,f 2(graf9.txt,ios: :out ) ;
void citete( )
{ int i,j ; f>>n;
for (i=1; i<=n; i++)
for (j=1;j<=n; j++) { f1>>a[i] [j];
if(a[i][j]==1) m++;}
m=m/2; f1.close( );}
void transforma( )
{int i,j,k=1;
for(i=1;i<=n;i++)
for(j=1;j<i;j++)
if(a[i][j]==1)
{b[i][k]=1; b[j][k]=1; k++;}}
void afieaz muchii( )
{ for (k=1;k<=m;k++) {cout<<muchia<<k<<: ;
for (int i=1; i<=n; i++)if(b[i][k]==1)
cout<<i<< ;
cout<<endl;}}
void afieaz_noduri_izolate( )
{ int i,k,x;
for (i=1; i<=n; i++)
{for (k=1,x=0,k<=m && x==0;k++)
if(b[i][k]==1) x=1;
if(!x)
cout>>i<< ;}}
void salveaz( )
{f2<<n<< <<m<<endl;
for (int k=1;k<=m;k++)
{ for (int i=1; i<=n; i++)if(b[i][k]==1)
f2<<i<< ;
f2<<endl;}
f2.close( );}
void main( )
{citete ( ); transform( ); afieaz_muchii( );
cout<<noduri izolate sunt:
afieaz_noduri_izolate( );
salveaz( );}
Graful orientat-Programul 8
#include<fstream.h>
int a [10][10],n,m,b[10][20];
fstream f 1(graf1.txt,ios: :in ) ,f 2(graf9.txt,ios: :out ) ;
void citete( )
{ int i,j ; f>>n;
for (i=1; i<=n; i++)
for (j=1;j<=n; j++) { f1>>a[i] [j];
if(a[i][j]==1) m++;}
f1.close( );}
void transforma( )
{int i,j,k=1;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(a[i][j]==1){b[i][k]=-1; b[j][k]=1; k++;}}
void afieaz_arce( )
{int i,k,x,y;
for (k=1;k<=m;k++)
{cout<<arcul<<k<<: ;
for (i=1; i<=n; i++)
if(b[i][k]==-1) x=i;if(b[i][k]==1) y=i;}
cout<<x<< -<<y<<endl;}}
void afieaz_noduri_izolate( )
{ int i,k,x;
for (i=1; i<=n; i++)
{for (k=1,x=0,k<=m && x==0;k++)
if(b[i][k]==1| | b[i][k]==-1) x=1;
if(!x)cout>>i<< ;}}
void salveaz( )
{int i,k;
f2<<n<< <<m<<endl;
for ( k=1;k<=m;k++)
{ for ( i=1; i<=n; i++){if(b[i][k]==-1) x=i;
if(b[i][k]==1) y=i;}
f2<<x<< -<<y<<endl;}f2.close( );}
void main( )
{citete ( ); transform( ); afieaz_arce( );
cout<<noduri izolate sunt:
afieaz_noduri_izolate( );salveaz( );}

II.2.3. Reprezentarea prin lista de adiacen
Lista de adiacen este format din listele Li (1in) care conin toi vecinii unui nod x
i

la care se poate ajunge direct din nodul x
i
, adic toate nodurile x
j
pentru care [xi, xj] U.
Observaie. n cazul grafului neorientat, lista L
i
a vecinilor unui nod x
i
al grafului este
format din nodurile x
j
adiacente nodului x
i
. n cazul grafului orientat, lista L
i
a vecinilor
unui nod x
i
al grafului este format din nodurile x
j
care sunt succesorii nodului x
i
.


Graful neorientat G
1


Graful orientat G
9






Implementarea acestui tip de reprezentare se poate face:
- static, folosind una dintre urmtoarele structuri de date:
o Matricea listei de adiacen
o Vectorii listei de adiacen
- dinamic, cu ajutorul listelor nlnuite.

Algoritmi pentru reprezentarea grafurilor folosind lista de adiacen

Din lista de adiacena implementat static cu matrice se pot obine urmtoarele
informaii:
Graf neorientat Graf orientat
Lungimea listei de adiacen a nodului i
neizolat, cu eticheta mai mic dect n, este
egal cu diferena dintre primul indice
j(j=i+1, n-1) diferit de 0, din prima
seciune a liniei a doua (L[1][j]0) i
Lungimea listei de adiacen a nodului i
neizolat, cu eticheta mai mic dect n, se
calculeaz la fel ca i n cazul grafului
neorientat. Pentru nodul n, lungimea listei
de adiacen este egal cu (n+m+1-
Nod Lista de
adiacen
1 2,3,4
2 1,3,5
3 1,2,4,5
4 1,3
5 2,3
6 7,8
7 6
8 6
Nod Lista de
adiacen
1 2
2 1,3,4
3 5
4 2,5
5 3,6
6 5
1 2 3
4 5 6
U
2
U
3
3
U
5
U
8
U
7
U
9
U
10
U
4
U
6
indicele coloanei din care ncepe lista de
adiacen a nodului i (L[1][j]-L[1[i]).
Pentru nodul n, lungimea listei de adiacen
este egal cu diferen dintre numrul total
de coloane, plus 1, i indicele coloanei din
care ncepe lista de adiacen a nodului n
(n+2xm+1-L[1][n]). Luungimea listei de
adiacena se mai poate determina prin
numrarea n linia a doua a elemontelor
diferite de 0, ncepnd cu elementul din
coloana L[1][i] , la care se adaug 1.
Gradul unui nod i este egal cu lungimea
listei de adiacen a nodului sau cu
numrul de apariii ale etichetei nodului n
a doua seciune a primei linii a matricei
L[0][j]=i, cu j=n+1,n+2*m.
L[1][n]).
Gradul extern al nodului i este egal, cu
lungimea listei de adiacen a nodului.
Gradul intern al nodului i, este egal cu
numrul de apariii ale etichetei nodului n
a doua seciune a primei linii a matricei
(L[0][j]=i, cu j=n+1, n+m).
Nodurile adiacente nodului i sunt nodurile
a cror etichet apare n lista de adiacen a
nodului i.
Succesorii nodului i sunt nodurile a cror
etichet apare n lista de adiacen a
nodului i.
Predecesorii nodului i sunt nodurile j n a
cror list de adiacen apare nodul i.
Nodurile adiacente nodului i sunt date de
reuniunea dintre mulimea succesorilor i
mulimea predecesorilor nodului.
Numrul de vecini ai nodului i este egal cu
gradul nodului.
Numrul de vecini ai nodului i este egal cu
cardinalul mulimii de noduri adiacente
nodului i.
Muchia [i,j] a grafului reprezint nodul i i
un nod j din lista de adiacen a nodului i
din prima linie a matricei .
Arcul [i][j] al grafului reprezint nodul i i
un nod j din lista de adiacen a nodului i
din vectorul L.



Implementarea algoritmilor pentru reprezentarea grafurilor cu lista de adiacen

1.Crearea listei de adiacen n implementarea static prin citirea listelor de vecini din
fiier. Determinarea gradului unui nod. Obinerea matricei de adiacen din matricea
listei de adiacen.
n programele 1 i 2, n fiierul text se gsesc urmtoarele informaii despre un graf
neorientat (i varianta orientat): pe prima linie, valorile pentru numrul de noduri n i
numrul de muchii m, desprite prin spaiu, iar pe urmtoarele n linii, desprite prin
spaiu, numrul de vecini ai unui nod i lista vecinilor (i varianta numrului de succesori
ai unui nod i lista succesorilor). Se citesc din fiierul text aceste informaii i se creeaz
lista de adiacen implementat cu matrice, respectiv cu vectori. Se afieaz nodurile cu
gradul cel mai mare. Se obine matricea de adiacen din lista de adiacen. Se salveaz
apoi matricea de adiacen ntr-un fiier text. n fiierul text se scriu: pe primul rnd
ordinul grafului, iar pe urmtoarele rnduri liniile matricei de adiacen. Funcia
cisteste() se folosete pentru a citi listele de adiacen din fiier, funcia grad() pentru a
determina gradul macim al nodurilor din graf, funcia transpune() pentru a obine
matricea de adiacen din lista de adiacen, iar funcia scrie() pentru a scrie matricea de
adiacen n fiier. Informaiile se citesc din fiierul text graf13.txt, pentru graful
neorientat, i graf14.txt, pentru graful orientat i se salveaz n graf15.txt, respectiv
graf16.txt se creeaz cu un editor de texte.
Graful neorientat i graful orientat- implementarea cu matrice
Programul 1
#include<fstream.h>
int n,m,L[3][50],a[10][10]; //pentru graful neorientat
fstream f1(graf13.txt,ios::in), f2(graf15.txt,ios::out); //pentru graful orientat
fstream f1(graf14.txt,ios::in) f2(graf16.txt,ios::out);
void citeste() {int i,j,x,k; f1>>n>>m; for(i=1;i<=n;i++) L[1][i]=i; j=n+1;
for(i=1;i<=n;i++) {f1>>x; if(x==0) l[2][i]=0; else {L[2][i]=j;
for(k=1;k<=x;k++) {f1>>L[1][j]; if(k!=x) l[2][j]=j+1; else L[2][j]=0; j++; }}}
f1.close();}
int grad(inti) {int g,j=L[2][i]; if(L[2][i]==0) g=0; else { g=1; while (L[2][j]!=0)
{g++;j++;}}
return g;}
int grad_max() {int i, max=0; for(i=1;i<=n;i++) if(grad(i)>max) max=grad(i); return
max;}
void transpune() {int i,j; for(i=1;i<=n;i++) {j=L[2][i]; if(L[2][i]!=0)
{while(L[2][j]!=0) {a[i][l[1][j]]=1; j++;} a[i][L[i][j]]=1;}}}
void scrie() {int i,j; f2<<n<<endl; for(i=1;i<=n;i++){for(j=1;j<=n;j++) f2<<a[i][j]<<
; f2<<endl;}
void main() {int i; citeste()
cout<<Gradul cel mai mare este <<grad_max()<<endl;
cout<<Nodurile cu gradul cel mai mare sunt: ;
for(i=1;i<n;i++) if(grad(i)==grad max() cout<<i<< ;
transpune(); scrie();}
Graful neorientat i graful orientat- implementarea cu vectori.
Programul 2
#include<fstream.h>
int n,m,L[50],a[10][10],cap[10];
fstream f1(graf13.txt,ios::in), f2(graf15.txt,ios::out); //pentru graful neorientat
fsteam f1(graf14.txt,ios::in), f2(graf16.txt,ios::out);// pentru graful orientat
void citeste() {int i,j=1,x,k; f>>n>>m; for(i=1;i<=n;i++) {f1>>x; if(x==0) cap[i]=0;
else cap[i]=j;
for(k=1;k<=x;k++) {f1>>L[j]; j++;}}} f1.close();}
int grad(int i) {int g,j; if(cap[i]==0) g=0; else {if i<n) {j=i+1; while(cap[j]==0 &&
j<n) j++;
if(j==n+1) g=2*m+1-cap[i]; //g=m+1-cap[i];//pentr graf orientat
else g=cap[j]-cap[i];} else g=2*m+1-cap[i];} return g;}
int grad max() {//este identica cu cea de la implementarea cu matrice}
void transpune() {int i,j; for(i=1;i<=n;i++) for(j=0;j<=grad(i); j++)
a[i][L[cap[i][j]]=1;}
void scrie() {//este identica cu cea de la implementarea cu matrice}
void main() }//este identica cu cea de la implementarea cu matrice}

2.Crearea listei de adiacen n implementarea dinamic prin citirea listei muchiilor din
fiier. Determinarea vecinilor i a gradului unui nod.
n programul 3 n fiierul text se gsesc urmtoarele informaii despre un graf
neorientat: pe prima linie, valorile pentru numrul de noduri n i numrul de muchii m,iar
de pe urmtoarele m linii, cte o pereche de numere desprite prin spaiu, care reprezint
etichetele nodurilor ce formeaz o muchie(arc). Se citesc din fiierul text aceste
informaii i se creeaz lista de adiacen implementat dinamic. Se afieaz vecinii i
gradul fiecrui nod. Funcia init() se folosete pentru a iniiaziza cu valoarea NULL
elementele vectorului L, funcia adauga_nod() pentr a aduga un nod naintea nodului
prim la lista simplu nlnuit a unui nod din graf, funcia creare() pentru a crea lista de
adiacen, funcia grad() pentru adetermina gradul unui nod, funcia afisare_vecini()
pentru a afia vecinii fiecrui nod, iar funcia afisare_grad() pentru a afia gradul fiecrui
nod. Informaiile se citesc din fiierul text graf11.txt pentru graful neorientat i graf12.txt
pentru graful orientat.
Programul 3













#include<fstream.h>
struct nod {int info; nod* urm;}; nod*L[20]; int n,m;
fstream f1(graf11.txt,ios::in);
void init()
f>>n>>m; for(int i=1;i<=n;i++) L[i]=NULL;}
void adauga_nod (nod*&prim, int y)
{nod *p=new nod; p->info=y; p->urm=prim; prim=p;}
void creare()
{int x,y;
while (f>>x>>y)
{adauga_nod(L[x],y); adauga_nod(L[y],x);} f.close();}
void afisare_vecini()
{for(int i=1;i<=n;i++) {cout<<Vecinii nodului<<i<<: ;
for(nod*p=L[i];p!=NULL; p=p->urm) cout<<p->info<< ; cout<<endl;}}
int grad(int i) {int g=0; for(nod*p=L[i]; p!=NULL; p=p->urm) g++; return g;}
void afisare_grade()
{for(int i=1;i<=n;i++) cout<<Gradul nodului <<i<< : <<grad(i)<<endl;}
void main() {init(); creare (); afisare_vecini(); afisare_grade();}


I.3. Conexitatea grafurilor
I.3.1. Lan.Ciclu.Drum.Circuit
Lanul

ntr-un graf G=(X,U) se definete lanul ca fiind o succesiune de noduri care au
proprietatea ca,oricare ar fi dou noduri succesive,ele sunt adiacente.
Graful neorientat
Dac mulimea nodurilor unu graf orientat este X={x
1
,x
2
x
n
},un lan de la nodul l
1
la
nodul l
k
-L(l
1
,l
k
)-va fi definit prin mulimea L(l1,lk)={l1,l2,li..lk}, unde l
i
X, pentru
orice i(1 i )..Lanul poate fi interpretat ca un traseu prin care se parcurg anumite
muchii ale grafului,traseul fiind ordinea n care se parcurg aceste muchi.Fiecare pereche
de noduri succesive din lan reprezint parcurgerea unei muchii.Dac exist L(x
i
,x
j
),se
spune c nodul x
j
este accesibil din nodul x
i.
.
Graful orientat
Dac mulimea nodurilor unui graf orientat este X={ x
1
,x
2
x
n
},un lan de la nodul 1 la
nodul k-
L(l
1
,l
k
) va fi definit prin mulimea L(l
1
,l
k
)= L(l1,lk)={l1,l2,li..lk},unde l
i
X ,pentru
orice i(1 i ). La definirea unui lan, nu se ine cont de orientarea arcelor,ci numai de
faptul c dou noduri sunt legat de de un arc.
Lungimea unui lan reprezint numrul de parcurgeri ale muchiilor, respective arcelor.
Dac o muchie (un arc) este parcurs de mai multe ori,se va numra fiecare din
parcurgerile sale.
Lanul de lungime minim dintre nodul x
i.
i nodul x
j
L
min
(x
i
,x
j
)-este lanul cu numrul
minim de muchii(arce),din mulimea nevid de lanuri L(x
i
,x
j
).Extremitile unui lan sunt
formate din nodul care ncepe i nodul cu care se termin lanul.
Exemple:
1.Pentru un graf neorientat G
19
=(X
19
,U
19
),definit astfel:
mulimea nodurilor este X
19
={1,2,3,4,5,6,7,8}.
mulimea muchiilor este
U
19
={[1,2],[1,5],[1,6],[2,3],[2,5],[2,6],[3,4],[3,6],[3,7],[3,8],[4,8],[5,6],[6,7],[7,8]}.
- L
1
(1,7)={1,2,3,8,4,3,6,5,2,3,7}este un lan ntre nodul cu eticheta 1 i nodul cu
eticheta 7 (figura 23).Lungimea lanului este 10.
- L
1
(1,7) definit anterior este un lan neelemetar,deoarece se repet nodul cu
eticheta 3.Este un lan compus,deoarece n lan se repet muchia [2,3].
- L
2
(1,7)={1,2,3,6,7} este un lan elementar deoarece fiecare nod este parcurs o
singura dat.
- L
3
(1,7)={1,6,3,2,6,7} este un lan simplu,deoarece nici o muchie nu se repet,dar
este un lan neelementar,deoarece se repet nodul cu muchia 6.

Fig.23 G
19


2.Pentru graful orientat G
20
=(X
20
,U
20
),definit astfel:
-mulimea nodurilor este X
20
={1,2,3,4,5,6,7}
-mulimea arcelor este
U
20
={[1,2],[1,3],[2,3],[2,4],[3,6],[3,7],[4,1],[4,5],[5,2],[5,4],[6,3],[6,5],[7,6]}
- L
1
(1,5)={1,2,5,6,3,6,7,6,5} este un lan ntre nodul cu eticheta 1 i nodul cu
eticheta 5(figura 24).Lungimea lanului este 8.


Fig.24 G
20

- L
1
(1,5) definit anterior este un lan neelementar,deoarece se repet nodul cu
eticheta 6.Este un lan compus,deoarece n lan se repet arcul[6,7]
- L
2
(1,5)={1,2,3,7,6,5} este un lan elementar, deoarece fiecare nod este parcurs o
singur dat.
- L
3
(1,5)={1,2,4,5,2,3,6,5} este un lan simplu,deoarece nici un arc nu se repet,dar
este un lan neelementar deoarece se repet nodul cu eticheta 2.

Algoritmi pentru determinarea lanurilor elementare ntr-un graf
1.Afiarea lanurilor elementare dintre dou noduri.
Algoritmul. Pentru generarea lanurilor elementare ntre nodul x i nodul y, se folosete
metoda backtracking. Nodurile lanului elementar vor fi generate n stiv. Primul nod din
stiv este nodul x. Condiia ca un nod adugat n stiv s fac parte din soluie (s fie
valid) este s formeze o muchie (un arc) cu nodul adugat anterior n stiv i s nu mai
existe n stiv (condiia ca lanul s fie elementar). Soluia se obine atunci cnd nodul
adugat n stiv este nodul y.
Implementarea algoritmului. n programul 1,se citete din fiierul text graf1.txt matricea
de adiacen a unui graf neorientat, respectiv, din fiierul graf2.txt matricea de aciacen a
unui graf orientat. Se mai citesc de la tastatur dou valori numerice care reprezint
etichetele a dou noduri din graf. Se caut toate lanurile lementare care exist ntre cele
dou noduri i se afieaz. Dac nu exist nici un lan elementar, se afiseaz un mesaj.
Funcia citete ( ) se folosete pentru a citi matricea de adiacen din fiier. Variabila este
se folosete pentru a verifica dac s-a gsit un lan elementar ntre cele dou noduri (are
valoarea 0 False, dac nu s-a gsit un lan elementar).
Programul 1
#include<fstream. h>
typedef stiva [100] ;
int a [20][20] , n , k , as , ev , x , y , este=0 ;
stiva st ;
fstream f ( graf1.txt , ios : :in ) ;
void citeste ( ) { // se citeste matricea de adiacenta din fisier }
void init ( ) {st [k]=0; }
int successor ( )
{if ( st [k]<n) {st [k]=st [k]+1; return 1;} else return 0;}
int valid ( )
{if ( k>1) //conditia ca doua noduri successive sa fie adiacente
if ( a[ st [k-1] ] [st [k]] = = 0) return 0;
//pentru graful orientat
// if (a[ st [k]] [st [k-1]] = =0 && a[st [k-1]] [st [k]] = =0) return 0;
for ( int i=1;i<k;i++) //conditia ca lantul sa fie elementar
if ( st [k] = =st [i] ) return 0;
return 1; }
int solutie ( ) { return st [k] = =y; }
//se obtine solutia atunci cand ultimul nod adaugat in stiva este y
void tipar ( )
{ for ( int i=1, este=1; i<=k; i++) cout<<st [i]<< ; cout<<endl; }
void bt ( ) { //partea fixa a algoritmului }
{k=2; init ( ) ;
while ( k>1 )
{ as=1; ev=0;
while ( as && !ev)
{as=successor ( ) ;
if (as) ev=valid ( ) ;}
if (as)
if (solutie ( ) ) tipar ( ) ;
else { k ++; init ( ) ; }
else k -- ; } }
void main ( )
{ citeste ( ) ; cout<<x= ; cin>>x; cout<<y= ; cin>>y; st [1] =x; bt ( ) ;
if (!este) cout<<Nu exista lant ; }

2.Afiarea tututror lanurilor elementare din graf.
Algoritmul. Pentru generarea tuturor lanurilor elementare din graf, se vor genera lanurile
elementare dintre nodul x (1xn) i nodul y (1yn), folosind metoda backtracking, care
se va apela pentru ficare pereche de noduri x i y (xy).
Implementarea algoritmului. n programul 2,se citete din fiierul text graf1.txt matricea
de adiacen a unui graf neorientat, respectiv, din fiierul graf2.txt matricea de aciacen a
unui graf orientat. Se caut toate lanurile elementare care exist n graf i se afieaz.
Dac nu exist nici un lan elementar, se afieaz un mesaj.
Programul 2
#include<fstream. h>
typedef stiva [100] ;
int a [20][20] , n , k , as , ev , x , y , este=0 ;
stiva st ;
fstream f ( graf1.txt , ios : :in ) ;
void citeste ( ) {//la fel ca n exemplul precedent }
void init ( ) {//la fel ca n exemplul precedent }
int succesor ( ) {//la fel ca n exemplul precedent }
int valid ( ) {//la fel ca n exemplul precedent }
int solutie ( ) {//la fel ca n exemplul precedent }
void tipar ( ) {//la fel ca n exemplul precedent }
void bt ( ) {//partea fix a algoritmului - ca n exemplul precedent }
void main ( )
{ citeste ( ) ;
for ( x=1;x<=n;x++ )
for ( y=1;y<=n;y++ ) if (x!=y) { st [1]=x; bt ( ) ;}
if ( !este ) cout<<Nu exista lanturi elementare ; }


3.Verificarea unui ir de etichete de noduri dac formeaz un lan simplu.
Algoritmul. Se verific dac:
-irul de etichete poate forma un lan (dac fiecare pereche de noduri consecutive din
lan este legat prin muchie, respectiv arc) ;
-lanul este simplu (se verific dac muchiile formate cu nodurile din lan nu se
repet).
Implementarea algoritmului. n programul 3,se citesc din fiierul text graf3.txt lista
muchiilor unui graf neorientat, respectiv, din fiierul graf.4txt lista arcelor unui graf
orientat. Se citete apoi, de la tastatur, un ir de k numere, care reprezint etichete ale
nodurilor din graf. Se verific dac acest ir de noduri poate reprezenta un lan simplu n
graf. irul de numere citite de la tastatur se memoreaz n vectorul v. n vectorul z cu
nregistrri de tip muchie, se memoreaz muchiile (arcele) pe care le formeaz dou
noduri succesive din irul de numere. Pentru a identifica dou muchii (arce) identice,
perechile de etichete care formeaz o muchie sunt memorate ordonat. Funcia citeste ( )
se folosete pentru a citi informaiile din fiier i pentru a le memora n matricea de
adiacen a grafului, funcia lant ( ) se folosete pentru a verifica dac irul de numere
poate reprezenta un lan din graf, funcia simplu ( ) se folosete pentru a verifica dac
lanul este un lan simplu.
Programul 3
#include<fstream. h>
struct muchie { int x, y ;} ;
muchie z [10];
int k, n, m, a [10][10], v [10] ;
fstream f ( graf3.txt, ios :: in) ;
void citeste ( )
{int i, x, y; f>>n>>m;
for (i=1;i<=m;i++) {f>>x>>y; a[x][y] =1; a [y][x] =1 ; } f.close ( ) ; }
int lant ( )
{for (int i=1;i<k;i++) if ( a[v[i]] [v[i+1]] ==0 ) return 0;
return 1;}
int simplu ( )
{for (int i=1;i<k;i++)
for (int j=i+1;j<=k;j++) if (z[i].x == z[j].x && z[i].y ==z[j].y) return 0;
return 1; }
void main ( )
{int i; citeste ( ); cout<<k= ; cin>>k;
for (i=1;i<=k;i++) {cout<<eticheta <<i<< = ; cin>>v[i] ; }
for (i=1;i<k;i++) if (v[i]<v[i+1] ) { z[i].x=v[i]; z[i].y=v[i+1] ;}
else { z[i].x=v[i+1]; z[i].y=v[i]; }
if ( lant ( ) )
if ( simplu ( ) ) cout<<este lant simplu ;
else cout<<nu este lant simplu ;
else cout<<nu este lant ; }

Ciclul

Un lan care are toate muchiile distincte dou cte dou i extremiti care coincide se
numete ciclu.Ciclul este un lan simplu ( [l
1
,l
2
] [l
2
,l
3
]; [l
1
,l
2
] [l
3
,l
4
]; ; [l
1
,l
2
] [l
k-
1
,l
k
]; [l
k
-2, l
k-1
] [l
k-1
,l
k
]), n care extremitile coincid: l
1
=l
k
.
Un graf fr cicluri se numete graf aciclic.
Dac toate nodurile unui ciclu sunt distincte dou cte dou, cu excepia extremitilor,
ciclul se numete ciclu elementar.
Exemple:
1.Pentru graful neorientat G
19
, figura 23:
- Lanul L
4
(1,1) = {1,2,3,6,2,1} nu este un ciclu deoarece n lan se repet muchia
[1,2].
- Lanul L
5
(1,1) = {1,2,6,3,7,6,1}= C
1
este un ciclu neelementar deoarece se repet
nodul cu eticheta 6.
- Lanul L
6
(1,1) ={1,2,3,7,6,1}= C
2
este un ciclu elementar deoarece nu se repet
nici un nod.
2. Pentru graful orientat G
20
, figura 24:
- Lanul L
4
(1,1) ={1,2,4,5,2,1} nu este un ciclu deoarece n lan se repet arcul
[1,2].
- Lanul L
5
(1,1) = {1,2,5,6,3,2,4,1}= C
1
este un ciclu neelemntar deoarece se repet
nodul cu eticheta 2.
- Lanul L
6
(1,1) = {1,2,3,6,5,4,1} este un ciclu elementar deoarece nu se repet nici
un nod.
3. Un circuit electric poate fi reprezentat cu ajutorul unui graf orientat, n care nodurile
reelei sunt nodurile grafului, iar sensul arcelor este dat de sensul ales pentru curentul
electric.




Algoritm pentru determinarea ciclurilor elementare ntr-un graf
Algoritmul. Se genereaz toate lanurile elementare care pornesc din nodul x (1xn), trec
prin cel puin trei noduri i se pot nchide cu nodul x. Pentru generarea acestor lanuri
elementare se folosete metoda backtracking, care se va apela pentru fiecare nod x.Soluia
se obine atunci cnd nodul adugat n stiv formeaz o muchie (un arc) cu nodul x i
stiva conine cel puin 3 noduri.
Implementarea algoritmului. n programul 4,se citete din fiierul text graf1.txt matricea
de adiacen a unui graf neorientat, respective, din fiierul graf2.txt matricea de adiacen
a unu graf orientat. Se caut toate ciclurile elementare care exist n graf i se afieaz.
Dac nu exist nici un ciclu elementar, se afieaz un mesaj.

Programul 4
#include<fstream. h>
typedef stiva [100] ;
int a [20][20] , n , k , as , ev , x , este=0 ;
stiva st ;
fstream f ( graf1.txt , ios : :in ) ;
void citeste ( ) { //se citete matricea de adiacen din fiier }
void init ( ) { //este identic cu cea de la afiarea lanurilor elementare }
int successor ( ) { //este identic cu cea de la afiarea lanurilor elementare }
int valid ( ) { //este identic cu cea de la afiarea lanurilor elementare }
int solutie ( ) { return a[ st[k] ] [x]==1 && k>2 ; }
// se obine soluia atunci cnd ultimul nod adugat este adiacent
// nodului x i n stiv exist cel puin trei noduri
void tipar ()
{for ( int i=1, este=1; i<=k; i++ ) cout<<st[i]<< ; cout<<x<<endl; }
void bt ( ) {partea fix a algoritmului }
void main ( )
{ citeste ( );
for ( x=1;x<=n;x++ ) { st[1]=x; bt ( ) ;}
if ( !este ) cout<<nu exista nici un ciclu elementar ; }

Drumul

ntr-un graf orientat G=(X,U) se definete un drum ca fiind o succesiune de noduri care
au proprietatea c oricare ar fi dou noduri successive ele sunt legate printr-un arc.
Dac, ntr-un graf orientat, mulimea nodurilor este X={x
1
,x
2
,,x
n
}, iar mulimea
arcelor este U={u
1
,u
2
,,u
m
}, un drum de la nodul d
1
la nodul d
k
D(d
1
,d
k
) va fi definit
prin mulimea nodurilor D(d
1
,d
k
)={d
1
,d
2
,,d
k
}, unde d
i
U, pentru orice i (1ik), iar
arcele [d
1
,d
2
],[d
2
,d
3
],[d
3
,d
4
],, [d
k-1
,d
k
] U. Drumul poate fi privit ca un lan n care
parcurgerea de la un nod la altul trebuie s se fac n sensul arcului care leag nodurile.
Dac exist D(x
i
,x
j
), se spune c nodul x
j
este accesibil din nodul x
i
.
- Lungimea unui drum este dat de numrul de arce care l compun. n cazul n care
arcele au asociate lungimi, lungimea unui drum este dat de suma lungimilor
arcelor care l compun.
- Drumul de lungime minim dintre nodul d
i
i nodul d
j
D
min
(d
i
,d
j
) este drumul
cu numrul minim de arce din mulimea nevid de drumuri D(d
i
,d
j
).
- Subdrumul este format dintr-un ir continuu de noduri din drum. De exemplu,
pentru lanul D(d
1
,d
k
)={d
1
,d
2
,, d
i
,.d
j
,,d
k
}, D
s
(d
i
,d
j
) definit astfel:
D
s
(d
i
,d
j
)={d
i
,d
i+1
,,d
j-1
,d
j
} este un subdrum al drumului D.
- Drumul elementar este drumul n care nodurile sunt distincte dou cte dou.
Drumul simplu este drumul n care arcele sunt distincte dou cte dou.
Exemple Pentru graful orientat G
20
(figura 24):
- Lanul L
7
(1,6) = {1,2,5,6} nu este un drum deoarece parcurgerea nu se face n
sensul sgeilor.
- Lanul L
8
(1,6) ={1,2,3,6,3,6} = D
1
este un drum neelementar, deoarece se repet
eticheta nodurilor 3 6 i compus deoarece prin arcul [3,6] s-a trecut de dou
ori.
- Lanul L
9
(1,6) ={1,2,3,7,6} = D
2
este un drum elementar, deoarece nu se repet
nici un nod.
- Lanul L
9
(1,6) = {1,2,4,5,2,3,6} = D
3
este un drum simplu, deoarece nici un arc nu
a fost parcurs de dou ori, dar este un drum neelementar, deoarece se repet nodul
cu eticheta 2.

Algoritmi pentru determinarea drumurilor elementare ntr-un graf orientat
1.Afiarea drumurilor elementare din graf.
Algoritmul. Se va folosi algoritmul pentru determinarea tuturor lanurilor elementare din
graf, la care elementul soluiei generat n stiv, la nivelul k (k>1), va fi considerat valid
numai dac trecerea de la nodul de pe nivelul k-1 la nodul de pe nivelul k se face, n graf,
n sensul arcului.
Implementarea algoritmului. n programul 5,se citete din fiierul graf2.txt matricea de
adiacen a unui graf orientat. Se caut toate drumurile care exist n graf i se afieaz.
Dac nu exist nici un drum elementar, se afieaz un mesaj.
Programul 5
#include<fstream.h>
typedef stiva [100];
int a [20][20] , n , k , as , ev , x , este=0 ;
stiva st ;
fstream f ( graf1.txt , ios : :in ) ;
void citeste ( ) { //se citete matricea de adiacen din fiier }
void init ( ) { //este identic cu cea de la afiarea lanurilor elementare }
int valid ( )
{ if ( k>1) if ( a[st [k-1]][st[k]] == 0 ) return 0;
for ( int i=1; i<k; i++ ) if ( st [k] == st [i] ) return 0;
return 1;}
int solutie ( ) { return st [k] ==y; }
void tipar ( )
{ for ( int i=1, este=1; i<k;i++ ) cout<<st[i]<< ; cout<<x<<endl; }
void bt ( ) { // partea fix a algoritmului }
void main ( )
{ citeste ();
for (x=1;x<=n;x++)
for ( y=1;y<=n;y++ ) if ( x!=y ) { st [1]= x; bt ( ); }
if ( !este ) cout<<nu exista ; }

2.Algoritmul Roy-Warshall de determinare a matricei drumurilor
Matricea drumurilor este o matrice ptrat binar de dimensiune n (n reprezentnd
ordinal grafului), definit astfel:

a[i][j] = 1, dac exist drum de la nodul i la nodul j
0, dac nu exist drum de la nodul i la nodul j

Informaiile din matricea drumurilor se pot folosi pentru a verifica dac exist drum
ntre dou noduri ale grafului.
Algoritmul. Dac nu exist nu arc de la nodul i la nodul j, considerm c exist un drum
de la nodul i la nodul j, dac exist un nod k (ki i kj) care are proprietarea c exist un
drum de la nodul i la nodul k i exist un drum de la nodul k la nodul j. Matricea
drumurilor se obine din matricea de adiacen prin transformri succesive, astfel: se
genereaz toate nodurile k (1kn), iar pentru fiecare nod k se genereaz toate perechile
de noduri i (ik) i j (jk) i se verific dac a[i][k] =1 i a[k][j] =1. n caz afirmativ, n
matricea de adiacen se atribuie valoarea 1 elementului a[i][j].






Fig.26 G
22


1
2
3 4 5

Pentru graful G
22
din figura 26 matricea de adiacen sufer urmtoarele cinci
transformri.
La fiecare transformare, dac drumul de la nodul i la nodul j trece prin nodul intermediar
k (drumul trece de la nodul i la nodul k i de la nodul k la nodul j), atunci elementului
a[i][j] i se va atribui valoarea 1.

Matricea de adiacen este:








k=1 k=2 k=3
0 1 0 0 0
0 0 1 0 0
1 1 0 1 0
0 0 0 0 1
0 0 0 1 0


k=4 4
k=5







Interpretarea datelor din matricea obinut n urma transformrilor se face astfel: exist
drum de la nodul i la nodul j dac a[i][j] =1. De exemplu, exist drum de la nodul 2 la
nodul 4, dar nu exist drum de la nodul 4 la nodul 2.
Implementarea algoritmului. n programul 6,se citete din fiierul graf20.txt matricea de
adiacen a unui graf orientat. Se afiesz toate perechile de noduri din graf ntre care
exist un drum. Funcia citeste ( ) se folosete pentru a citi matricea de adiacen din
fiier. Funcia transforma ( ) se folosete pentru a transforma matricea de adiacen n
matricea drumurilor. Matricea de adiacen va suferi n transformri succesive (pentru
fiecare nou valoare a lui k), astfel: fiecare element a[i][j] cu ik i jk, este nlocuit cu
valoarea produsului a[i][k]*a[k][j] ceea ce este echivalent cu a atribui valoarea 1
acestui element dac a[i][k] =1i a[k][j] =1. Funcia afiseaza ( ) se folosete pentru a
afia toate perechile de noduri i i j ntre care exist drum. Aceste perechi sunt
0 1 0 0 0
0 0 1 0 0
1 1 0 1 0
0 0 0 0 0
0 0 0 1 0
1 1 1 1 0
1 1 1 1 0
1 1 1 1 0
0 0 0 0 1
0 0 0 1 0
0 1 1 0 0
0 0 1 0 0
1 1 1 1 0
0 0 0 0 1
0 0 0 1 0
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
0 0 0 1 1
0 0 0 1 1
1 1 1 1 0
1 1 1 1 0
1 1 1 1 0
0 0 0 0 1
0 0 0 1 1
identificate n matricea drumurilor ca fiind indicele pentru linie i indicele pentru coloan
ale elementelor care au valoarea 1.
Programul 6
#include<fstream.h>
int a [20][20], n;
fstream f (graf20.txt, ios :: in);
void citeste ( ) { se citete matricea de adiacen din fiier}
void transforma( )
{ for ( int k=1; k<=n; k++ )
for ( int i=1; i<=n; i++ )
for ( int j=1; j<=n; j++ )
if ( a[j][j] ==0 && i!=k && j!=k ) a [i][j] = a[i][k]*a[k][j]; }
void afiseaza( )
{ cout<< exista drum intre perechile de noduri <<endl;
for ( int i=1;i<=n; i++ )
for ( int j=1; j<=n; j++ )
if ( a[i][j] ==1 && i!=j ) cout<< ( <<i<< , <<j<< ) << ; }
void main ( ) { citeste( ); transforma( ); afiseaza( ); }

Complexitatea algoritmului Roy-Warshall
Algoritmul de transformare a matricei de adiacen n matricea drumurilor are ordinal de
complexitate O(n*n*n)=O(n
3
), deoarece fiecare structur repetitiv for se execut de n
ori, iar structurile for sunt imbricate.

Circuitul

ntr-un graf orientat un drum care are toate arcele distincte dou cte dou i extremiti
care coincid se numete circuit.
Circuitul este un drum simplu (arcele sunt distincte dou cte dou n care extremitile
coincid). Circuitul elementar este circuitul n care toate nodurile sunt distincte dou
cte dou,cu excepia primului i a ultimului-care coincid.
Exemple pentru graful orientat G
20,
figura 24 :
- Lanul L
10
(1,1)={1,2,3,6,3,6,3,7,6,5,4,1}nu este un circuit, deoarece arcele [3,6]
si [6,3] au fost parcurse de dou ori.
- Lanul L
11
(1,1)={1,2,3,6,7,5,2,4,1}=C
1
este un circuit neelementar,deoarece se
repet eticheta nodurilor 3 i 6.
- Lanul L
12
(1,1)={1,2,3,7,6,5,4,1}=C
2

este un circuit elementar , deoarece nu se
repet eticheta nici unui nod.

Algoritm pentru determinarea circuitelor elementare ntr-un graf orientat:
Programul 7
#include <fstream.h>
typedef stiva[100];
int a[20][20],n,k,as,ev,x,este=0;
stiva st;
fstream f(graf2.txt,ios:; in);
void citeste() {// se citete matricea de adiacen din fiier}
void init() {//identific cu cea de la afiarea lanurilor elementare}
int successor() {//identific cu cea de la afiarea lanurilor elementare}
int valid()
{if (k>1) if (a[st[k-1]] [st[k]==0 return 0;
for (int i=1;i<k;i++) if (st[k]==st[i]) return 0;
return 1;}
int solutie() {return a[st[k]] [x]==1 && k>1;}
//se obine soluia atunci cnd ultimul nod adugat este adiacent
//nodului x i n stiv exist cel puin dou noduri
void tipar ()
{for (int i=1,este=1;i<=k;i++) cout<<st[i]<< ;cout<<x<<endl;}
void bt() {//partea fix a algoritmului }
void main() {citete ();
for (x=1;x<=n;x++) {st[1]=x;bt();}
if (!este) cout<<nu exist circuite;}

I.3.2. Graful conex. Componenta conex
Un graf se numete graf conex dac are proprietatea c, pentru orice pereche de noduri
diferite ntre ele ,exist un lan care s le lege.
Exemplul 1:
1)graful neorientat G
19
=(X
19
,U
19
),definit anterior este un graf conex, deoarece oricare ar
fi dou noduri din mulimea X
19
,ele pot fi legate printr-un lan.
2)Graful orientat G
20
=(X
20
,U
20
), definit anterior este un graf conex,deoarece oricare ar fi
dou noduri din mulimea X
20
,ele pot fi legate printr-un lan.
Dac un graf G=(X,U) nu este conex,se poate defini un subgraf conex al grafului G,
adic se poate defini o mulime X
`
C X care s induc subgraful G
`
=( X
`
,U
`
),ce are
proprietatea c este conex.
Dac un graf G=(X,Y) nu este conex , se numete component conex a grafului, un
subgraf conex al su C=( X
`
,U
`
),n raport cu aceast proprietate ( conine un numr
maxim de noduri din G care au proprietatea c sunt legate cu un lan).
Un graf conex are o singur component conex(graful nsui).
Numrul minim de muchii necesare pentru ca un graf neorientat ,cu n noduri ,s fie
conex este
n-1(m n-1).

Graful tare conex

Un graf orientat G se numete graf tare conex dac are proprietatea c , pentru orice
pereche de noduri diferite ntre ele , exist un drum care s le lege.






Exemplul 1:

Graful G
20

1)Graful orientat G
20
=(X
20
,U
20
) este un graf tare conex , deoarece exist un circuit
elementar care trece prin toate nodurile grafului:{1,2,3,7,6,4,1} , altfel spus ,oricare ar fi
dou noduri din mulimea X
20
, ele pot fi legate printr-un drum.
Dac un graf G=(X,U) nu este conex , se numete component tare conex a grafului un
subgraf conex C= (X
`
,U
`
) al su , maximal n raport cu aceast proprietate (conine
numrul maxim de noduri din G care au proprietatea c sunt legate printr-un drum).
Un graf tare conex are o singur component tare conex(graful nsui).
Componenta tare conex din care face parte un nod este dat de intersecia dintre
subgraful predecesorilor i subgraful succesorilor acelui nod.
Graful componentelor tare conexe ale unui graf care nu este tare conex G=(X,U) se
obine prin reducerea fiecrei componente conexe la un nod.
Exemplul 2 :
n graful orientat din figura 29 ,G
25
= (X
25
,U
25
) :

Fig.29

Componentele tare conexe sunt C
1
={1,2,3} , C
2
={4,5,6} i C3={7}

Algoritmi pentru determinarea conexitii grafurilor
1.Determinarea componentelor conexe ntr-un graf.
Algoritmul. O component conex este format din toate nodurile ntre care exist un lan
elementar. Deoarece un nod nu poate s aparin dect unei componente conexe, se va
folosi un vector cu n elemente pentru a memora nodurile care au fost deja nregistrate
ntr-o component conex. Iniial, elementele vectorului au valoarea 0 (niciun nod nu a fost
nregistrat ntr-o component conex), iar dac un nod x va fi adugat la o component
conex, valoarea elementului x din vector va fi 1. Pentru a verifica dac exist un lan
elementar ntre dou noduri x i y se folosete metoda backtracking.Acest algoritm poate fi
folosit att n grafurile neorientate, ct i n grafurile orientate. Mai poate fi folosit i pentru
a verifica dac un graf este conex : fie se verific dac ntre nodul 1 i fiecare dintre
celelalte noduri ale grafului exist un lan elementar, fie se verific dac prima component
conex obinut conine toate nodurile grafului.
Implementarea algoritmului. n programul 1, se citete din fiierul graf19.txt matricea de
adiacen a unui graf neorientat (varianta din fiierul graf20.txt matricea de adiacen a
unui graf orientat) i se afieaz componentele conexe. n vectorul v se memoreaz
nodurile care au fost deja nregistrate ntr-o component conex. Variabila este se folosete
pentru a verifica dac s-a gsit un lan elementar ntre dou noduri (are valoarea 0 False,
dac nu s-a gsit un lan elementar). Variabila m se folosete pentru a numra
componentele conexe identificate. Funcia citete () se folosete pentru a citi matricea de
adiacen din fiier. Funcia componente() se folosete pentru a afia componentele conexe
ale grafului: pentru fiecare nod x (1xn ) care nu a fost afiat ntr-o component conex
(v[x]= 0), se caut toate nodurile y (1yn i yx) care sunt legate cu un lan elementar de
nodul x. Pentru un nod y gsit, se marcheaz n vectorul v faptul c a fost adugat la o
component conex (v[y]= 1). Programul 1


























#include<fstream.h>
typedef stiva [100];
int a [20][20], n, k, as, ev, x, y, v[20], este =0;
stiva st;
fstream f (graf19.txt)
void citete () (// se citete matricea de adiacen din fiier)
void init () (//identic cu cea de la afiarea lanurilor elementare)
int succesor () (//identic cu cea de la afiarea lanurilor elementare)
int valid () (// identic cu cea de la afiarea lanurilor elementare)
int solutie () {return st [k]==y;}
// se obine soluia atunci cnd ultimul nod adugat n stiv este y.
void tipar () {este=1;}
// dac exist soluie (un lan ntre nodurile x i y)
// variabila este va avea valoarea 1.
void bt () { // identic cu cea de la afiarea lanurilor elementare}
void component ()
{int m = 0;
for ( x=1; x<=n; x++)
if (v[x]== 0)
{m++ ; st[1]=x; v[x]= 1;
cout<< componenta conex<<m<<: <<x<<_ ;
for(y=1; y<=n; y++)
if (x!= y) {este= 0; bt();
if (este) { v[y]= 1; cout<<y<< ; }}
cout<<endl; }}
void main()
{citeste(); componente ();}





2.Determinarea componentelor conexe ntr-un graf orientat.
Algoritmul. O component conex este format din toate nodurile ntre care exist un
drum, cel puin de la un nod la altul (drumul nu trebuie s asigure legtura n ambele
sensuri). Altfel spus, dac exist un drum de la un nod x la un nod y, cele dou noduri x
i y aparin aceleiai componente conexe chiar dac nu exist i un drum de la nodul y
la nodul x. i n acest algoritm se folosete un vector cu n elemente pentru a memora
nodurile care au fost deja nregistrate ntr-o component conex. Pentru a verifica dac
exist un drum de la nodul x la nodul y se folosete matricea drumurilor.
Pentru graful G
22
din figura 26 , n matricea drumurilor se observ c exist drum de la
nodul 1 la oricare celelalte 4 noduri din graf. Graful are o singur component conex.








Graful G
22
- Fig.26

Matricea de adiacen


Implementarea algoritmului. n programul 2,se citete din fiierul graf20.txt matricea de
adiacen a unui graf orientat i se determin dac graful este conex. Dac nu este, se
afieaz componentele conexe. n vectorul v se memoreaz nodurile care au fost deja
nregistrate ntr-o component conex. Funcia citeste () se folosete pentru a citi
matricea de adiacen n fiier. Funcia transforma() se folosete pentru a afia
componentele conexe ale grafului pentru fiecare nod i(1in) care nu a fost afiat ntr-o
component conex (v[i]=0), se caut toate nodurile j (1jn i ji) la care ajunge un
drum ce pornete din nodul i . Pentru un nod j gsit, se marcheaz n vectorul v faptul c
a fost adugat la o component conex (v[j]=1).
Programul 2
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
0 0 0 1 1
0 0 0 1 1
1
2
3 4 5

3. Determinarea componentelor tare conexe ntr-un graf orientat.
Algoritmul. O component tare conex este format din toate nodurile i i j ntre care
exist un drum elementar de la nodul i la nodul j, dar i invers. Se folosete un vector cu
n elemente, pentru a memora nodurile care au fost deja nregistrate ntr-o component
tare conex. Iniial, elementele vectorului au valoarea 0, iar dac un nod i va fi adugat la
o component conex, atunci i=1.
Implementarea algoritmului.Se folosete metoda backtracking.n programul 3,se citete
din fiierul graf20.txt matricea de adiacen a unui graf orientat. Dac nu este conex se
afieaz componentele tare conexe. Variabila este1 se folosete pentru a verifica dac s-a
gsit un drum elementar de la nodul i la nodul j. Variabila este2 se folosete pentru a
verifica dac s-a gsit un drum elementar de la nodul j la nodul i, iar variabila este se
folosete pentru a verifica dac s-a gsit un drum elementar de la nodul x la nodul y. n
vectorul v se memoreaz nodurile care au fost deja nregistrate ntr-o component tare
conex. Variabila m se folosete pentru a numra componentele conexe identificate.
Funcia citeste() se folosete pentru a citi matricea de adiacen din fiier. Funcia
componenete() se folosete pentru a afia componentele tare conexe ale grafului.
Programul 3
#include<fstream.h>
typedef stiva[100]
int a [20] [20], n, y[20];
fstream f(graf20.txt, ios::in);
void transforma()
{for (int k=1;k<=n; k++)
for (int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
if ( a[i][j]==0 && 1!=k && j!=k)
a[i][j] = a[i][k]*a[k][j];}
void component()
{int i, j, n=0;
for(int i=1; i<=n; i++)if (v[1]==0)
{m++; v[i] =1; cout<<component conexa<<m<<: <<i<<_;
for (int j=1; j<=n; j++)
if(a[i][j] ==1 && i!=j)
{v[j]=1; cout<<j<< ;}
cout<<endl;}}
void main()
{citeste() ; transforma() ; componente();}










I.4. Parcurgerea grafului

Parcurgerea grafului reprezint operaia prin care sunt examinate n mod sistematic
nodurile sale, pornind de la un nod dat i, astfel nct fiecare nod accesibil din nodul i pe
muchiile (arcele) adiacente s fie atins o singur dat. Vecinii unui nod sunt reprezentai
de toate nodurile adiacente lui i accesibile din el.
Vizitarea sau traversarea unui graf este operaia prin care se parcurge graful trecndu-se
de la nodul i (nodul current) la nodurile vecine lui , ntr-o anumit ordine, n vederea
prelucrrii informaiilor asociate nodurilor. Pentru parcurgerea grafurilor, exist
urmtoarele dou metode:
- Metoda de parcurgere n lime- BREADTH FIRST (BF). Se viziteaz mai nti
un nod iniial i, apoi vecinii acestuia , apoi vecinii nevizitai ai acestora .a.m.d.
pn cnd se parcurg toate nodurile grafului.
#include<fstream.h>
typedef stiva[100];
int a[20][20], n, k, as, ev, x, y, v[20], este1, este2, este=0;
stiva st;
fstream f (graf19.txt, ios::in);
void citeste()
void init()
int successor()
int valid()
int solutie()
{return st[k]==y;}
void tipar() {este=1;}
void bt()
void component()
{int i, j, m=0;
for(i=1; i<=n; i++)
if(v[i]==0)
{m++; v[i]=1; cout<<componenta conexa<<m<<:<<i<< ;
for (j=1; j<=n; j++)
if(j!=i)
{x=i; y=j; st[1]=x; este=0; bt(); este1=este; x=j; y=i; st[1]=x; este=0; bt() ; este2=este;
if (este1 && este2 ) {v[j]=1; cout<<j<< ;}}
cout<<endl;}}
void main() {citeste(); componente();}

- Metoda de parcurgere n adncime- Depth First(DF). Se viziteaz mai nti un
nod iniial i, dup care se parcurge primul dintre vecinii si nevizitai, de exemplu
j, dup care se trece la primul vecin nevizitat al lui j, .a.m.d.- pn cnd se
parcurge n adncime ramura respectiv . Cnd s-a ajuns la captul ei, se revine la
nodul din care s-a plecat ultima dat, i se parcurge urmtorul su vecin nevizitat.

I.4.1. Parcurgerea n lime Breadth First (BF)
Pentru aceast metod de parcurgere a unui graf cu n noduri, se folosesc urmtoarele
structuri de date i date elementare :
o variabilele de memorie: n pentru numrul de noduri ale grafului, k pentru nodul
care se prelucreaz , i i j pentru parcurgerea matricei de adiacen i a
vectorilor.
o matricea de adiacen a grafului a.
o vectorul de vizitare vizitat. El conine n elemente n care se nregistreaz nodurile
vizitate. Elementele vectorului vizitat[i] sunt definite astfel :
vizitat[i] = 1 dac nodul i a fost vizitat
0, dac nodul i nu a fost vizitat nc
o coada de ateptare c a nodurilor parcurse.
Coada de ateptare c gestioneaz nodurile prelucrate. Pentru coada de ateptare se
folosete implementarea static cu un vector c cu n elemente. Pentru gestionarea cozii de
ateptare se folosesc dou variabile de memorie prim i ultim care joac rolul de
indicatori pentru a memora adresa primului element din list(capul cozii) i, respectiv,
adresa ultimului element din list (coada cozii).n aceast coad de ateptare vor fi
nrergistrate nodurile vizitate n ordinea n care au fost vizitate. Iniial , coada de ateptare
conine un singur element care corespunde nodului cu care ncepe parcurgerea grafului,
iar valoarea indicatorilor prim i ultim este 1. Pe msur ce se parcurge graful , se
completeaz urmtoarele elemente ale vectorului c. Atunci cnd se prelucreaz nodul k
de la capul cozii de ateptare , prin coada cozii de ateptare se introduc toate nodurile i
vecine cu nodul k care nu au fost vizitate nc .
Algoritmul pentru parcurgerea grafului este urmtorul:
PAS1. Se citete din fiier valoarea pentru variabila n i matricea de adiacen a grafului.
PAS2. Se iniializeaz cu 0 elementele vectorului de vizitare vizitat, deoarece iniial nici
unul dintre noduri nu a fost vizitat.
PAS3. Se introduce de la tastatur valoarea variabilei de memorie k , corespunztoare
primului nod cu care ncepe producerea grafului.
PAS4. Se iniializeaz coada de ateptare c, astfel : prim 1,ultim 1 i c[prim] k,
deoarece , n coada de ateptare c este nregistrat doar nodul k cu care ncepe parcurgerea.
PAS5. Se actualizeaz vectorul vizitat atribuind elementului k al vectorului valoarea 1,
deoarece a fost vizitat (vizitat[k] 1).
PAS6. Ct timp coada nu este vid (prim<=ultim) execut
PAS7. Se extrage urmtorul element din coada de ateptare ,corespunztor nodului
cruia i se vor vizita vecinii(k c[prim];)
PAS8. Pentru toate nodurile i vecine ale vrfului k, nevizitate nc , execut
PAS9. Se incrementeaz valoarea indicatorului ultim , pentru a nregistra
urmtorul nod care va trebui vizitat prin adugarea la coada cozii de ateptare(ultim
ultim+1;).
PAS10. Se adaug la sfritul cozii de ateptare c , nodul i vecin nodului k, care
nu a fost nc vizitat (c[ultim] i;)
PAS11. Prin adugarea nodului j la coada de ateptare c se consider c acest nod
a fost vizitat i se actualizeaz elemental din vectorul de vizitare care corespunde acestui
nod
(vizitat[i] 1;). Se revine la pasul 6.
PAS12. Se pregtete indicatorul prim pentru a se extrage urmtorul nod din coada
de ateptare ai crui vecini vor fi vizitai(prim prim +1;). Se revine la pasul 7.
PAS13. Se afieaz lista nodurilor vizitate , n ordinea n care au fost vizitate , prin
extragerea lor din vectorul c, pornind de la elementul 1 i pn la elementul n.
Pentru implementarea algoritmului se folosesc subprogramele:
o Funcia procedural citete creeaz matricea de adiacen prin prelucrarea
informaiilor din fiierul f;
o Funcia procedural init iniializeaz coada de ateptare cu primul nod vizitat;
o Funcia operand este_vida testeaz coada de ateptare dac este vid ;
o Funcia procedural adaug adaug un nod la coada de ateptare ;
o Funcia procedural elimina elimin nodul prelucrat din coada de ateptare;
o Funcia procedural prelucrare prelucreaz primul nod din coad: adaug la
coada de ateptare toi vecinii nevizitai ai acestui nod i apoi l elimin din
coada de ateptare;
o Funcia procedural afisare afieaz nodurile grafului n ordinea prelucrrii.
Matricea de adiacen se citete din fiierul text graf21.txt .Pentru implementare se
folosete programul urmtor Programul 1.


















Complexitatea algoritmului de parcurgere n lime
int n, a[10][10], vizitat[20], c[20], prim, ultim, k;
fstream f(graf21.txt, ios :: in);
void citeste ()
void init(int k) {prim =ultim= 1 ; c[ultim]=k; vizitat[k]=1;}
int este_vida() {return ultim<prim;}
void adauga(int i) {ultim ++; c[ultim]=j; vizitat[j]=1;}
void elimina() {prim ++; }
void prelucrare(){int i; k=c[prim];
for (i=1;i<=n;i++) if (a[k][i]==1 && vizitat[i]== 0)
adauga (i); elimina() }
void afisare (){for (int i=1; i<=n ; i++)cout<<c[i]<< ;}
void main()
{citeste () ; cout<<nod de pornire: ; cin>>k; int (k);
while (!este_vida () ) prelucrare ();
cout<<nodurile vizitate prin metoda BF sunt : << endl;
afisare ();}
Algoritmul const in eliminarea unui nod din coada de ateptare i adugarea vecinilor
(succesorilor) si n coada de ateptare.Fiecare nod va fi adugat n coada de ateptare o
dat i, prin urmare, va fi eliminat din coada de ateptare o singur dat. Complexitatea
operaiilor de eliminare a celor n noduri din coada de ateptare este O(n). Pentru a aduga
noduri la coada de ateptare, sunt examinai vecinii (succesorii) nodului curent. Vecinii
(succesorii) unui nod sunt examinai o singur dat, atunci cnd nodul este eliminat din
coada de ateptare. Numrul total de vecini examinai este egal cu m numrul de muchii
(arce) ale grafului. Complexitatea operaiilor de adugare de noduri este O(m).
Complexitatea algoritmului este liniar O(m+n).

I.4.2. Parcurgerea n adncime Depth First
Pentru aceast metod de parcurgere a unui graf cu n noduri se folosesc urmtoarele
structuri de date i date elementare:
o Variabilele de memorie n pentru numrul de noduri ale grafului , k pentru nodul
care se prelucreaz, i i j pentru parcurgerea matricei de adiacen i a vectorilor.
o Matricea de adiacen a grafului a.
o Vectorul de vizitare vizitat. El conine n elemente n care se nregistreaz nodurile
vizitate. Elementele vectorului vizitat[i] sunt definite ca i n metoda precedent
de parcurgere.
o Stiva st a nodurilor parcurse. Stiva st gestioneaz nodurile vecine parcurse n
adncime.
Pentru gestionarea stivei se folosete variabila de memorie vf pentru a identifica ultimul
nod intrat n stiv. Pentru stiv se folosete implementarea static cu un vector st cu n
elemente. n stiv vor fi nregistrate, n ordine, nodurile vizitate n adncime, pe o
direcie. Iniial, stiva conine un singur element care corespunde nodului cu care ncepe
parcurgerea grafului, iar valoarea variabilei vf este 1. Pe msur ce se pargurge graful, se
completeaz urmtoarele elemente ale vectorului st. Atunci cnd se prelucreaz un nod k,
pe la vrful stivei se introduc n stiv toate nodurile i vecine cu nodul k care nu au fost
vizitate nc.
Algoritmul pentru parcurgerea grafului este urmtorul:
PAS1. Se citete din fiier valoarea pentru n i matricea de adiacen a grafului.
PAS2. Se iniializeaz cu 0 elementele vecorului de vizitare vizitat, deoarece nici unul
dintre
nici unul dintre noduri nu a fost vizitat.
PAS3. Se introduce de la tastatur valoarea variabilei de memorie k, corespunztoare
primului nod cu care ncepe parcurgerea grafului, i se afieaz eticheta lui.
PAS4. Se iniializeaz stiva st (vrful i conintul vrfului stivei), astfel: vf1;
st[vf]k;
deoarece iniial n stiva st este nregistrat doar nodul k cu care ncepe parcurgerea.
PAS5. Se actualizeaz vectorul vizitat atribuind elementului k al vectorului valoarea 1,
deoarece a fost vizitat (vizitat [k]1).
PAS6. Ct timp stiva nu este vid (vf<>0) execut
PAS7. Se extrage din vrful stivei, elemntul corespunztor nodului cruia i se vor
vizita vecinii (kst[vf];).
PAS8. Se iniializeaz nodul i cu care ncepe cutarea (i1;).
PAS9. Ct timp nu s-a gsit un nod i vecin nodului k, nevizitat nc (i<=n i
a[i][k]=0 sau a[i][k]=1 i vizitat [i]=1 execut
PAS10. Se trece la urmtorul nod, n vederea verificrii (ii+1;), i se revine la
PAS9.
PAS11. Dac nu s-a mai gsit un nod i vecin nodului k nevizitat nc, atunci se
elimin nodul k din stiv, prin coborrea vrfului stivei (vfvf-1), altfel se afieaz nodul
gsit i, se adaug n vrful stivei (vfvf+1; st[vf]i;) i se actualizeaz elementul din
vectorul de vizitare care corespunde acestui nod, deoarece prin adugarea nodului i la
stiva st se consider c acest nod a fost vizitat (vizitat[i]1;) i se revine la PAS6.
Pentru implementarea algoritmului se folosesc subprogramele:
- funcia procedural citeste creeaz matricea de adiacen prin preluarea
informaiilor din fiierul f;
- funcia procedural init iniializeaz stiva dac este vid;
- funcia operand este_vida testeaz stiva dac este vid;
- funcia procedural adauga adaug un nod n stiv;
- funcia procedural elimina elimin nodul din vrful stivei;
- funcia procedural prelucrare prelucrez nodul din vrful stivei: caut primul
vecin
nevizitat i dac gsete un astfel de nod, l afieaz i l adaug n stiv; altfel, nodul
din vrful stivei este eliminat (nu mai are vecini nevizitai);
Programul 2 se aplica grafurilor neorientate.Pentru grafurile orientate, n funcia
prelucrare() condiia structurii repetitive while este: i<=n && ((a[k][i]==0 || a[i][k]==0) ||
((a[k][i]==1 || a[i][k]==1) && vizitat [i]==1))
Programul 2
int n, a[10][10], vizitat[20], st[20], vf, k;
fstream f (graf21.txt,ios::in);
void citeste() {//se citete matricea de adiacen din fiier}
void init (int k) {vf=1; st[vf]=k; vizitat[k]=1;}
int este_vida() {return vf==0}
void adauga (int i)
{vf++; st[vf]=i; vizitat[i]=1;}
void elimina ()
{vf--;}
void prelucrare()
{int i=1; k=st[vf];
while (i<=n && (a[k][i]==0 || (a[k][i]==1 && vizitat [i]==1))) i++;
if (i==n+1) elimina();
else {cout<<i<< ; adauga(i);}}
void main()
{citeste (); cout<<nodul de pornire: ; cin>>k;
cout<<Nodurile vizitate prin metoda DF sunt: <<endl;
cout<<k<< ;
init(k);
while (!este_vida() ) prelucrare();}


Complexitatea algoritmului de parcurgere n adncime
Algoritmul const n extragerea unui nod din stiv i adugarea vecinilor (succesorilor)
si n stiv, iar dac nu mai are vecini, va fi eliminat din stiv o singura dat.
Complexitatea operaiilor de eliminare a celor n noduri din stiv este O(n). Pentru a
aduga noduri n stiv sunt examinai vecinii (succesorii) nodului din vrful stivei.
Numrul total de vecini examinai este egal cu m-numrul de muchii (arce) ale grafului.
Complexitatea operaiilor de adugarea de noduri este O(m). Complexitatea algoritmului
este liniar O(m+n).



Determinarea conexitii grafurilor cu ajutorul algoritmului de parcurgere n
adncime
1.Afiarea componentelor conexe dintr-un graf.
Algoritmul. Identificarea mulimii de noduri care formeaz o component conex se face
parcurgnd n adncime graful pornind de la un nod iniial. Nodul cu care ncepe
parcurgerea n adncime pentru o component conex se caut printre nodurile nevizitate
nc. Graful se va parcurge n adncime pn cnd vor fi vizitate toate nodurile. Dac
graful este conex, se va afia o singur component conex care va fi format din toate
nodurile grafului.
Implementarea algoritmului. Se citete din fiierul graf21.txt matricea de adiacen a a
grafului neorientat i se afieaz toate componentele conexe ale grafului. n programul
3,pe lng variabilele i structurile de date folosite de algoritmul de parcurgere n
adncime se mai folosete variabila global m, pentru a numra componentele conexe.
Pentru a gsi nodul cu care se iniializeaz parcurgerea se folosete funcia cauta() care
caut primul nod nevizitat, n ordinea etichetelor nodurilor.
Programul 3
int n, a[10][10], vizitat[20], st[20], vf, k, m;
fstream f (graf21.txt, ios::in);
void citeste() {//se citete matricea de adiacen din fiier}
int cauta()
{for (int i=1; i<=n; i++) if (vizitat [i]==0) return i;
return 0;}
void init (int k) {vf=1; st[vf]=k; vizitat[k]=1;}
int este_vida() {return vf==0;}
void adaug (int i) {vf++; st[vf]=i; vizitat[i]=1;}
void elimin() {vf--;}
void prelucrare()
{int i=1; k=st[vf];
while (i<=n && (a[k][i]==0 || (a[i][k]==1 && vizitat[i]==1))) i++;
if (i==n+1) elimin(); else {cout<< ; adaug(i);}}
void main()
{citeste(); k=cauta();
while (k)
{m++; init(k); cout<<endl<<Componenta conexa <<m<<: <<k<< ;
while (!este_vida() ) prelucrare();
k=cauta();}}

2.Afiarea componentelor tare conexe dintr-un graf orientat.
Algoritmul. Nodul cu care ncepe parcurgerea n adncime pentru o component tare
conex se caut printre nodurile nevizitate nc. Pentru acest nod se determin mulimea
nodurilor care formeaz subgraful succesorilor i mulimea nodurilor care formeaz
subgraful predecesorilor. Prin intersecia celor dou subgrafuri (mulimi de noduri) se
obine componenta tare conex. Identificarea celor dou mulimi de noduri se face
parcurgnd n adncime graful pentru fiecare mulime, pornind de la un nod iniial. Un
nod se consider vizitat numai dac a fost adugat la o component tare conex.
Prelucrarea componentelor tare conexe prin parcurgerea n adncime a grafului se va face
pn cnd vor fi vizitate toate nodurile. Dac graful este tare conex, se va afia o singur
component tare conex care va fi format din toate nodurile grafului.
Implementarea algoritmului. Se folosete programul 4 n care se citete din fiierul
graf20.txt matricea de adiacen a a grafului orientat i se afieaz toate componentele
tare conexe ale grafului. Vectorii pred si succ se folosesc pentru a determina subgraful
predecesorilor, respectiv subgraful succesorilor nodului care se prelucreaz. Vectorii au n
elemente. Fiecare element i are valoarea 1 dac nodul i aparine subgrafului
predecesorilor, respectiv subgraful succesorilor; altfel, are valoarea 0. Funcia zero() se
folosete pentru a iniializa cu valoarea 0 vectorii pred si succ nainte de prelucrarea unei
componente tare conexe. Pentru a gsi nodul cu care se iniializeaz o component tare
conex, se folosete funcia cauta() care caut primul nod nevizitat, n ordinea etichetelor
nodurilor. Funciile prelucrare1() si prelucrare2() se folosesc pentru a parcurge graful n
adncime n vederea determinrii subgrafului predecesorilor, respectiv subgrafului
succesorilor nodului care se prelucreaz.Funcia comp() se folosete pentru a determina
nodurile unei componente tare conexe prin intersecia vecorilor pred i succ.
Programul 4
int n, a[10][10], vizitat[20], st[20], vf, m;
fstream f (graf20.txt, ios::in);
void citeste() {//se citete matricea de adiacen din fiier}
int cauta() {//este identic cu cea de la exemplul anterior}
void zero() (int x[]) {for (int i=1; i<=n; i++) x[i]=0;}
void init (int k) {vf=1; st[vf]=k;}
int este_vida() {return vf==0;}
void adaug (int i, int x[]) {vf++; st[vf]=i; x[i]=1;}
void elimin() {vf--;}
void prelucrare1 (int x[])
{int i=1, k=st[vf]; x[k]=1;
while (i<=n && (a[i][k]==0 || (a[i][k]==1 && x[i]==1))) i++;
if (i==n+1) elimin(); else adaug (i, x);}
void prelucrare2 (int x[])
{int i=1, k=st[vf]; x[k]=1;
while (i<=n && (a[k][i]==0 || (a[k][i]==1 && x[i]==1))) i++;
if (i==n+1) elimin(); else adaug (i, x);}
void comp (int x[], int y[])
{for (int i=1; i<=n; i++)
if (x[i]==1 && y[i]==1) {cout<<i<< ; vizitat[i]=1;}}
void main()
{int k, pred[10], succ[10];
citeste(); k=cauta(); m++; cout<<componentele tare conexe: <<endl;
while (k)
{cout<<endl<<m<<: ; init (k); zero(pred);
while (!este_vida() ) prelucrare1 (pred);
init (k); zero (succ);
while (!este_vida() ) prelucrare2 (succ);
comp (pred, succ); k=cauta(); m++;}}

I.5. Graful ponderat
Considerm un graf G=(X,U) i o funcie f:UR
+
care asociaz fiecrei muchii (arc) u
un numr real pozitiv (care poate avea semnificaia de cost, distan, timp, durat),
numit n general costul muchiei. Funcia f se numete funcia cost.
Un graf G=(X,U) pentru care s-a definit o funcie cost se numete graf ponderat.

o Graful ponderat se mai numete i graf cu costuri.
o Grafurile ponderate se folosesc n aplicaii n care trebuie determinat valoarea
minim sau valoarea maxim a unei mrimi asociate grafului, adic a funciei
cost.
o Se definete costul unui drum de la nodul x la nodul y ca fiind suma costurilor
muchiilor (arcelor) care formeaz acel drum.
o Metoda cea mai adecvat pentru reprezentarea unui graf ponderat este matricea
costurilor.
Exemplu Graful G
27
din figura 32.



Studiu de caz
Scop: exemplificarea unei aplicaii n care pentru reprezentarea datelor se folosete un
graf ponderat.
Exemplul 1. O firm deine depozite de marf n mai multe localiti. O reea de osele
leag direct unele dintre aceste localitti. Distana dintre dou localiti este msurat n
kilometri. S se determine traseul pe care s-l parcurg o main pentru a transporta
Fig.32 Graful G
27

marfa de la depozitul din oraul A la depozitul din oraul B astfel nct distana parcurs
n kilometri s fie minim.
Localitile formeaz nodurile unui graf neorientat n care fiecare muchie reprezint o
legatur direct pe osea ntre dou localiti. Fiecare muchie are asociat o mrime
distana . Aceast mrime este costul muchiei, iar graful este un graf ponderat. Cerina
problemei este de a determina un drum cu lungime minima (cu costul minim) ntre dou
noduri ale grafului.
Exemplul 2. O persoan trebuie s se deplaseze cu autoturismul ct mai repede ntre dou
intersecii din ora. Traficul ntre dou intersecii nu este ntotdeauna n ambele sensuri.
Cunoscnd timpul mediu de deplasare ntre dou intersecii, s se determine care este
traseul pe care trebuie s-l aleag pentru a ajunge de la intersecia A la intersecia B ct
mai repede.
Interseciile formeaz nodurile unui graf orientat n care fiecare arc reprezint sensul de
circulaie peo strad care leag direct dou intersecii. Fiecare arc are asociat o mrime
timpul mediu de parcurgere. Aceast mrime este costul muchiei, iar graful este un graf
ponderat. Cerina problemei este de a determina un drum cu timpul de parcurgere minim
(cu costul minim) ntre dou noduri ale grafului.


I.5.1. Matricea costurilor

Matricea costurilor unui graf este o matrice ptratic de dimensiune n (A
n,n
), ale crei
elemente a
i,j
sunt definite astfel nct s pun n eviden costul asociat fiecrei muchii
(arc).
n funcie de cerina aplicaiei, exist dou forme de reprezentare a matricei costurilor:
- Matricea costurilor minime pentru a determina valoarea minim a funciei cost;
- Matricea costurilor maxime pentru a determina valoarea maxim a funciei cost


a) Matricea costurilor minime. Elementele a
i,j
ale matricei sunt definite astfel:
c, daca exist o muchie (un arc) cu costul c>0 ntre nodurile i i j, cu i=j
a
i,j
= 0, dac i=j
, dac nu exist o muchie (un arc) ntre nodurile i i j, cu i=j
Fiecrei muchii (arc) care nu exist n graf i se asociaz o valoare foarte mare, deoarece,
cutndu-se costul minim, aceast muchie (arc) nu va mai fi selectat. Deoarece pentru
implementarea matricei nu se poate folosi simbolul , n locul lui se va folosi cea mai
mare valoare care se poate reprezenta n calculator pentru tipul de dat asociat costului.
Exemplu. Pentru graful ponderat G
27
din figura 32 matricea costurilor minime este
prezentat alturat.

1 2 3 4 5
1 0 4 3

2

0

7 8
3

0

4

4 0

5 2

2 0

b) Matricea costurilor maxime. Elementele a
i,j
ale matricei sunt definite astfel:
c, dac exist o muchie (un arc) cu costul c>0 ntre nodurile i i j, cu i=j
a
i,j
0, dac i=j
-, dac nu exist o muchie (un arc) ntre nodurile i i j, cu i=j
Fiecrei muchii (arc) care nu exist in graf i se asociaz o valoare foarte mic, deoarece,
cutndu-se costul maxim, aceast muchie (arc) nu va mai fi selectat. Deoarece pentru
implementarea matricei nu se poate folosi simbolul -, n locul lui se va folosi cea mai
mic valoare ce se poate reprezenta n calculator pentru tipul de dat asociat costului.

Algoritmul pentru crearea matricei costurilor
Pentru a crea matricea costurilor trebuie s se citeasc pentru fiecare muchie (arc)
nodurile de la extremiti i costul asociat fiecrei muchii (arc). Aceste informaii se pot
citi de la tastatur sau dintr-un fiier. Algoritmul pentru crearea matricei costurilor este:
PAS1. Se iniializeaz matricea astfel: toate elementele de pe diagonala principal cu
valoarea 0, iar restul elementelor cu valoarea corespunztoare pentru (-).
PAS2. Se actualizeaz matricea cu informaiile despre costurile asociate muchiilor
(arcelor) astfel: pentru fiecare muchie (arc) [i,j] cu costul c, elementului a[i][j] i se va
atribui valoarea costului c.
Implementarea algoritmului pentru matricea costurilor minime a unui graf orientat.
Pentru iniializarea matricei costurilor se folosete funcia init(), iar pentru actualizarea ei
funcia citire(). Elementele matricei fiind de tip int nu se poate folosi pentru simbolul
constanta de sistem MAXINT, deoarece n algoritmii de determinare a drumului cu costul
minim prin adunrile repetate ale elementelor matricei (care pot avea i valoarea
MAXINT) se depete capacitatea de reprezentare a tipului int. Exist dou soluii:
-Pentru elementele matricei se alege tipul long, chiar dac acest tip de dat nu este
justificat de valorile foarte mici ale costurilor (i se obine o utilizare ineficient a
memoriei interne)
-Se definete o constant cu o valoare foarte mare n comparaie cu celelalte costuri.
n implementarea algoritmului n programul 1 s-a ales varianta unei constante definite
MAX. datele se citesc din fiierul text cost.txt, n care pe prima linie exist un numr care
reprezint numrul de noduri ale grafului, iar pe urmtoarele rnduri cte trei valori
numerice separate prin spaiu, care reprezint nodurile de la extremitatea unui arc i i j
i costul asociat unui arc c.
Programul 1
#include <fstream.h>
int a[100][100], n;
int const MAX=5000;
fstream f (cost.txt , ios :: in);
void init() //se initializeaza matricea costurilor
{int i,j; f>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) if (i==j) a[i][j]=0;
else a[i][j]=MAX ;}
void citire() //se actualizeaza matricea costurilor cu date din fisier
{int i, j, c;
while (f>>i>>j>>c) a[i][j]=c; f.close();}
void main() {}


I.5.2. Algoritmul pentru determinarea costului minim (maxim)

Pentru determinarea drumului cu costul minim (maxim) ntre dou noduri ale unui graf
se poate folosi:
- algoritmul Roy-Floyd;
- algoritmul Dijkstra.

Algoritmul Roy-Floyd
Algoritmul folosete un principiu asemntor cu cel care a fost utilizat pentru
determinarea matricei drumurilor: gsirea drumului optim ntre dou noduri oarecare i i j
prin descoperirea drumurilor optime care l compun i care trec prin nodurile k se face
prin transformarea matricei costurilor. Matricea trece prin n transformari, n urma crora
fiecare element a[i][j] va memora costul drumului minim dintre nodurile i i j.
PAS1. Pentru etichete ale nodului k de la 1 la n (adic pentru orice nod al grafului)
execut:
PAS2. Pentru orice pereche de noduri din graf i i j (cu 1sisj i 1sjsn) execut:
PAS3. Dac suma dintre costul drumului de la i la k i costul drumului de la k la j
(a[i][k]+[k][j]) este mai mic dect costul drumului de la i la j (a[i][j]), atunci n
matricea costurilor costul drumului direct de la i la j este inlocuit cu costul drumului care
trece prin nodul k (a[i][j]=a[i][k]+a[k][j]).
Pentru graful din figura de mai jos matricea costurilor sufera urmatoarele 5
transformri. La fiecare transformare,dac drumul de la nodul i la nodul j are costul mai
mare dect costul drumurilor care trec prin nodul intermediar k (de la nodul i la nodul k i
de la nodul k la nodul j), atunci elementului a[i][j] i se va atribui valoarea a[i][k]+a[k][j].

k=1 k=2







k=3
1 2 3 4 5
1 0 4 3

2

0

7 8
3

5 0

4

4 0

5 2 6 5 2 0
1 2 3 4 5
1 0 4 3 11 12
2

0

7 8
3

5 0 12 13
4

4 0

5 2 6 5 2 0

k=4 k=5
1 2 3 4 5
1 0 4 3 11 12
2

0 11 7 8
3

5 0 12 13
4

4 0 17
5 2 6 5 2 0

Interpretarea datelor din matricea obinut n urma transformrilor se face astfel: drumul
de la nodul i la nodul j are costul minim a[i][j]. De exemplu, drumul cu costul minim de
la nodul 2 la nodul 4 are costul minim 7. Matricea nu furnizeaz informaii despre
etichetele drumului cu costul minim.
Pentru implementarea algoritmului se folosesc subprogramele:
- funcia procedural init iniializeaz matricea costurilor;
- funcia procedural citire actualizeaz matricea costurilor cu datele din fiier;
- funcia procedural transformare transform matricea costurilor;
- funcia procedural afisare afieaza lungimea drumurilor minime ntre toate
nodurile grafului.
Implementarea algoritmului se realizeaz cu programul urmtor:
Programul 2
#include <fstream.h>
int a[100][100], n;
int const MAX=5000;
fstream f("cost.txt", ios::in);
void init() {//se initializeaza matricea costurilor}
void citire() {//se actualizeaza matricea costurilor cu datele din fisier}
void transformare() //se transforma matricea costurilor
{for (int k=1;k<=n;k++)
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (a[i][k]+a[k][j]<a[i][j]) a[i][j]=a[i][k]+a[k][j];}
void afisare()
{cout<<"costul drumurilor minime intre nodurile: "<<endl;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (a[i][j]<MAX && i!=j) cout<<"("<<i<<","<<j<<")-"<<a[i][j]<<endl;}
void main()
1 2 3 4 5
1 0 4 3 11 12
2

0

7 8
3

5 0 12 13
4

4 0 17
5 2 6 5 2 0
1 2 3 4 5
1 0 4 3 11 12
2

0 11 7 8
3

5 0 12 13
4

4 0 17
5 2 6 5 2 0
{init(); citire(); transformare(); afisare();}

Informaiile din matricea costurilor transformat prin algoritmul Roy-Floyd se pot folosi
pentru a verifica dac exist drum cu costul minim ntre dou noduri ale grafului, iar n
caz afirmativ, se poate afia lungimea lui i se poate descoperi drumul.
Algoritmul de descoperire a drumului cu cost minim pornind de la matricea
costurilor transformat folosete acelasi raionament ca la transformarea ei: dac
lungimea drumului minim dintre nodurile i i j este egal cu suma dintre lungimile
minime a dou noduri care trec printr-un nod intermediar k (a[i][k]+a[k][j]=a[i][j]),
atunci nodul k face parte din drumul de lungime minim de la i la j. Deoarece problema
pentru determinarea nodurilor care formeaz drumul de lungime minim se descompune
n dou subprobleme: determinarea drumului minim de la nodul i la nodul k (cu k=i) i
determinarea drumului minim de la nodul k la nodul j (cu k=j), n implementarea
algoritmului se folosete strategia divide et impera.
Pentru implementarea algoritmului prin care se determina drumul minim dintre doua
noduri x i y (a caror eticheta se citeste de la tastatura) se folosesc subprogramele:
- funcia procedural init iniializeaz matricea costurilor;
- funcia procedural citire actualizeaz matricea costurilor cu datele din fiier;
- funcia procedural transformare transform matricea costurilor;
- funcia procedural drum determin drumurile cu cost minim;
- funcia procedural afisare afieaz costul drumului minim i nodurile care
formeaz drumul;
Programul 3
#include <fstream.h>
int a[100][100], n;
int const MAX=5000;
fstream f(cost.txt, ios::in);
void init() {//se initializeaza matricea costurilor}
void citire() {//se actualizeaza matricea costurilor cu datele din fisier}
void transformare() //se transforma matricea costurilor
void drum (int i, int j) //se determina nodurile drumului minim
{int k, gasit;
for (k=1,gasit=0; k<=n && !gasit; k++)
if (i!=k && j!=k) && a[i][j]=a[i][k]+a[k][j])
{drum(I,k); drum (k,j); gasit=1;}
if ( !gasit) cout<<j<< ;}
void afisare (int x, int y)
{if (a[x][y]<MAX)
{cout<< Drumul minim de la nodul <<x<< la nodul <<y ;
cout<<are costul <<a[x][y]<<endl;
cout<<x<< ; drum(x,y) ;}
else cout<<Nu exista drum;}
void main(){int x, y ; ; cin>>x ;cin>>y ;
init() ; citire() ; transformare() ; afisare(x,y) ;}

Complexitatea algoritmului Roy-Floyd
Algoritmul de transformare a matricei costurilor are ordinul de complexitate
O(nnn)=O(n
3
) deoarece fiecare structur repetitiv for se execut de n ori, iar
structurile for sunt imbricate. Algoritmul de determinare a drumurilor cu costul minim
din matricea costurilor transformat are ordinul de complexitate al algoritmului divide et
impera: O(nlg
2
n). Ordinul algoritmului este: O(n
3
)+O(nlg
2
n)=O(n
3
+nlg
2
n)=O(n
3
).

Algoritmul Dijkstra
Algoritmul lui Dijkstra construiete drumurile cu costul minim care pornesc de la un nod
oarecare x - nodul surs - pn la fiecare nod din graful G(X,U) - nodul destinaie.
Algoritmul ntreine o mulime cu nodurile care au fost deja selectate - S, i o coad de
prioriti Q cu nodurile care nu au fost selectate nc: Q= X-S, astfel:
o un nod y este declarat selectat atunci cnd s-a determinat costul final al drumului
cu costul minim de la nodul surs x la el. Selectarea unui nod nu este echivalent
cu gsirea drumului cu costul minim deoarece este posibil ca n urma calculrii
costului s rezulte c nu exist un drum de la nodul x la acel nod.
o n coada Q prioritatea cea mai mare o are nodul
pentru care costul drumului are valoarea cea mai
mic dintre toate costurile de drumuri care pornesc de
la nodul x la celelalte noduri neseletate nca. La
fiecare extragere a unui nod din coada de prioriti Q,
nodul este adugat la mulimea S, iar coada de
prioriti este reorganizat n funcie de acest nod (se
recalculeaz costul drumurilor de la nodul x la
nodurile rmase n coada, considernd c unele
drumuri, dac trec i prin nodul extras, pot s-i
micoreze costul). Pentru calcularea drumurilor de
lungime minim se intreine o mulime D n care se
memoreaz costul drumurilor de la nodul x la
nodurile neselectate, costuri care se recalculeaz la
fiecare extragere de nod.
Drumul cu costul minim care pornete din nodul x este
format din nodul iniial x i crete pn cnd coada de prioriti Q nu mai conine noduri.
Deoarece, cele dou mulimi S i Q sunt disjuncte, iar reuniunea lor este mulimea
nodurilor X, este suficient s se ntrein numai mulimea S. Algoritmul folosete strategia
Greedy, deoarece ntotdeauna alege nodul cel mai apropiat de nodul surs x.
PAS1. Se iniializeaz: S=C, se citete nodul iniial x i se atribuie multimii S.
PSA2. Se iniializeaz mulimea D cu costurile drumurilor de la nodul x la toate celelalte
noduri ale grafului (sunt preluate din matricea costurilor elementele a[x][i]).
PAS3. Ct timp coada de prioriti Q nu este vid (mai exist noduri neselectate) execut:
PAS4. Se caut printre nodurile neselectate nodul y cel mai mic cost al drumului
(reprezint elementul care trebuie eliminat din coada de prioriti Q).
PAS5. Se adaug nodul y la mulimea S: S=S{y} (nseamn extragerea nodului
y din coada de prioriti Q i declararea lui ca nod selectat).
PAS6. Pentru fiecare nod neselectat (nod din coada de prioriti) execut:
PAS7. Se recalculeaz costul drumului de la nodul x la acest nod folosind
ca nod intermediar nodul extras.
PAS8. Dac acest cost este mai mic dect cel din mulimea D, atunci el va
fi noul cost.
Implementarea algoritmului. Se folosesc trei vectori:
o Vectorul s pentru mulimea nodurilor selectate, definit astfel:
s(i)= 0, dac nodul i nu a fost selectat
1, dac nodul i a fost selectat
Iniial, elementele vectorului s au valoarea 0, cu exceptia elementului s[x] care are
valoarea 1. La terminarea execuiei programului, toate elementele din vectorul s
vor
avea valoarea 1. Nodurile i pentru care s[i]=0 se consider c fac parte din
coada
de prioriti Q.
o Vectorul d conine costul drumurilor, astfel: d[i]= costul drumului minim gsit la
un moment dat de la nodul x la nodul i (cu 1sisn). Iniial d[i]=a[x][i]. La
terminarea algoritmului, d[i]= costul minim al drumului de la nodul x la nodul i.
o Vectorul t memoreaz drumurile gsite ntre nodul x i celelalte noduri i ale
grafului. Memorarea drumului se face prin legtura cu predecesorul care este
definit astfel: p[i] memoreaz nodul j care este predecesorul nodului i pe drumul
la x, cu excepia nodului surs pentru care p[x]=0. Iniial, pentru toate nodurile i
care nu au costul infinit (pentru care nu exist un arc de la nodul x la nodul i),
p[i]=x; altfel, p[i]=0.
Nodul i care se extrage din coada de prioriti Q trebuie s ndeplineasc urmatoarele
condiii
o s[i]=0.
o d[i]=min{d[j] | 1sjsn; s[j]=0}.
d[i] reprezinta costul minim al drumului de la nodul x la nodul i.
Pentru reorganizarea cozii de prioriti se procedeaz astfel: pentru fiecare nod j cu
s[j]=0 se calculeaz costul drumului de la nodul x la nodul j care trece prin nodul i:
d[i]+a[i][j]. Dac acest cost este mai mic dect d[j], atunci aceasta va fi noua valoare a
lui d[j] i se actualizeaz vectorul p: p[j]=i.


Pentru graful din figura 32, considernd x=1, algoritmul se execut astfel:
Iniial:
Vectorii 1 2 3 4 5
s 1 0 0 0 0
d 0 4 3

Fig.32 - Graful G
27

p 0 1 1 0 0

Drumul cu costul cel mai mic este cu nodul 3: d[3]=3. Nodul 3 se va extrage din coada Q.
Se analizeaz nodurile care rmn n coada de prioriti:
Nodul 2. d[3]+a[3][2] = 3+5=8>4. Nu se modific nimic.
Nodul 4. d[3]+a[3][4] = 3+=>4. Nu se modific nimic.
Nodul 5. d[3]+a[3][5] = 3+=>4. Nu se modific nimic.


Vectorii 1 2 3 4 5
s 1 0 1 0 0
d 0 4 3

p 0 1 1 0 0

Drumul cu costul cel mai mic este cu nodul 2: d[2]=4. Nodul 2 se va extrage din coada Q.
Se analizeaz nodurile care rmn n coada de prioriti:
Nodul 4. d[2]+a[2][4] = 4+7=11<. Se modifica: d[4] = 11 si p[4] = 2.
Nodul 5. d[2]+a[2][5] = 4+8=12<. Se modifica: d[5] = 12 si p[5] = 2.

Vectorii 1 2 3 4 5
s 1 1 1 0 0
d 0 4 3 11 12
p 0 1 1 2 2

Drumul cu costul cel mai mic este cu nodul 4: d[4]=11. Nodul 4 se va extrage din coada
Q. Se analizeaz nodurile care rmn n coada de prioriti:
Nodul 5. d[4]+a[4][5] = 11+=>12. Nu se modific nimic.

Vectorii 1 2 3 4 5
s 1 1 1 1 0
d 0 4 3 11 12
p 0 1 1 2 2

Drumul cu costul cel mai mic este cu nodul 5: d[5]=15. Nodul 5 se va extrage din coada
Q. Coada este vid i se termin execuia algoritmului.
Final:
Vectorii 1 2 3 4 5
s 1 1 1 1 1
d 0 4 3 11 12
p 0 1 1 2 2

Din datele care se regsesc n vectorii d i p la terminarea algoritmului se obin
urmtoarele informaii:
o d[i] reprezint costul minim al drumului de la nodul x la nodul i. De exemplu,
pentru nodul 4 costul minim este 11.
o Din vectorul predecesorilor se reconstituie drumul cu costul minim de la nodul x
la nodul i. De exemplu, pentru nodul 4: p[4]=2, iar p[2]=1. Drumul este: 124.
Pentru implementarea algoritmului n care se determin drumul cu costul minim dintre
dou noduri x i y (a cror etichet se citete de la tastatur) se folosesc subprogramele:
- funcia procedural init iniializeaz matricea costurilor;
- funcia procedural citire actualizeaz matricea costurilor cu datele din fiier;
- funcia procedural generare_drum transform vectorii d i p conform
algoritmului pentru a obine drumurile cu costul minim de la nodul x la oricare alt
nod i din graf;
- funcia procedural drum determin nodurile drumului cu cost minim de la nodul
x pn la un nod i din graf - folosind informaiile din vectorul p;
- funcia procedural afisare afieaz lungimea drumurilor minime care pornesc
din nodul x pn la fiecare nod i din graf i nodurile care formeaz drumul;
Algoritmul se implementeaz cu programul 4.
Programul 4
#include <fstream.h>
int a[100][100], d[100], s[100], p[100], n;
int const MAX=5000;
fstream f("cost.txt",ios::in);
void init() {//se initializeaza matricea costurilor}
void citire() {//se actualizeaza matricea costurilor cu datele din fisier}
void generare_drum(int x) //se genereaza drumurile
{int i, j, min, y; s[x]=1;
for(i=1;i<=n;i++)
{d[i]=a[x][i];
if (i!=x && d[i]<MAX p[i]=x;}
for(i=1;i<=n-1;i++)
{for(j=1,min=MAX; j<=n; j++)
if (s[j]==0 && d[j]<min) {min=d[j]; y=j;}
s[y]=1;
for(j=1;j<=n;j++)
if (s[j]==0 && d[j]>d[y]+a[y][j]) {d[j]=d[y]+a[y][j]; p[j]=y;}}}
void drum(int i)
{if (p[i]!=0) drum(p[i]); cout<<i<<" "; }
void afisare (int x)
{for(int i=1;i<=n;i++)
if (i!=x)
if (p[i]!=0)
{cout<<"drumul cu costul minim de la nodul "<<x;
cout<<" la nodul"<<i<<" are costul "<<d[i]<<endl;
drum(i); cout<<endl;}
else cout<<"Nu exista drum de la "<<x<<" la "<<i<<endl;}
void main()
{int x; cout<<"x=";cin>>x;
init(); citire(); generare_drum(x); afisare(x);}

Complexitatea algoritmului Dijkstra
Pentru determinarea drumului cu costul minim se execut paii algoritmului. Pasul 2 are
ordinul de complexitate O(n). Pasul 3 se execut pentru fiecare nod din graf, mai putin
nodul surs, deoarece fiecare nod trebuie selectat o dat (se execut de n-1 ori). Pentru
fiecare nod selectat se analizeaz celelalte noduri, executndu-se: Pasul 4 de n ori (se
caut printre toate cele n noduri dac mai exist n coada de prioriti, iar printre cele care
mai sunt n coada de prioriti se caut nodul cu costul drumului cel mai mic), iar Pasul 6
de n ori deoarece trebuie identificate printre cele n noduri care mai sunt n coada de
prioriti. Ordinul de complexitate al algoritmului pentru determinarea drumului cu costul
minim va fi: O(n)+O(n(n+n))=O(n)+O(n
2
)=O(n
2
). n algoritmul pentru afiarea
drumului sunt analizate toate cele n noduri ale grafului, iar pentru fiecare nod i se
determin recursiv drumul. Complexitatea algoritmului de afiare va fi O(n)
O(nlg
2
n)=(n
2
lg
2
n).

I.6.Grafuri speciale
I.6.1. Graf nul.Graf complet.Graf parial.Subgraf
Graful nul

Graful G=(X,U) se numete graf nul dac mulimea U este vid (U=), adic graful nu
are muchii. Reprezentarea sa se face prin noduri izolate.
Exemplul 1: Graful N=(X,V) unde mulimea X={1,2,3,4} este mulimea nodurilor, iar
mulimea V= este mulimea muchiilor este un graf nul ( graful are noduri dar nu are
muchii).

Matricea de adiacen a unui graf nul este matricea zero ( nu conine nici un element cu
valoarea 1).

Graful complet

Un graf cu n noduri este un graf complet dac are proprietatea c, oricare ar fi dou
noduri ale grafului, ele sunt adiacente. El se noteaz cu K
n
.
Exemplul 2:






3 4
1
2
1 1
1 1
Se poate construi un singur graf neorientat complet, cu n noduri, deoarece ntre dou
noduri, x i y, exist o singur muchie [x,y].
Numrul m de muchii ale unui graf neorientat complet, cu n noduri K
n
. este:
m=n(n-1)/2.
Numrul de grafuri orientate complete care se pot construi cu n noduri este egal cu
n
k
=3
C
2
2
.
n cazul matricei de adiacen a unui graf neorientat complet, valoarea fiecrui element
care nu se gsete pe diagonala principal este 1.
n cazul matricei de adiacen a unui graf orientat complet- pentru orice pereche de
noduri i i j, diferite ntre ele (ij)- a[i][j]=1 sau a[j][i]=1.
Numrul minim de arce ntr-un graf orientat complet cu n noduri este egal cu numrul de
muchii ale grafului neorientat complet K
n
.
Numrul maxim de arce ntr-un graf orientat complet cu n noduri este egal cu dublul
numrului de muchii ale grafului neorientat complet K
n
.

Algoritmi pentru prelucrarea grafurilor complete
1.Algoritm pentru a determina numrul minim de arce care trebuie adugate la un graf
orientat, pentru a obine un graf orientat complet.
Algoritmul. Se numr perechile de noduri i i j (ij) ntre care nu exist nici un arc.
Implementarea algoritmului. n programul 1, informaiile despre graful orientat se citesc
din fiierul text gc.txt: de pe prima linie numrul de noduri, i apoi, de pe urmtoarele
rnduri matricea de adiacen.
Programul 1
#include<iostream.h>
int n,a[10][10];
fstream f(gc.txt,ios::in);
void citeste() {//se citeste matricea de adiacenta din fisier}
void main()
{int i,j,m=0; citeste();
for(i=2;i<=n;i++) if(a[i][j]==0 && a[j][i]==0) m++;
cout<<Numarul de arce care trebuie adaugate este <<m;}

2.Algoritmul pentru a determina numrul maxim de noduri izolate pe care poate s le
conin un graf neorientat care are n noduri i m muchii.
Algoritmul. Se identific graful complet care se pote forma astfel nct s consume ct
mai multe muchii(mmax) din cele m muchii ale grafului(mmax<=m). Graful complet
astfel obinut are n1 noduri: mmax= n1[(n1-1)/2]<=m. Numrul de noduri n1 este partea
ntreag din rdcina pozitiv a ecuaiei de gradul II: n1=[(1+1+8xm)/2]. Pentru
diferena de muchii rmase(m-mmax) mai este necesar un nod, pentru a lega aceste
muchii de nodurile grafului complet care s-a format. Numrul de noduri izolate este: n-
n1-1.
Programul 2
#include<iostream.h>
#include<math.h>
void main()
{int m,n,n1; cout<<muchii= ; cin>>m; cout<<noduri ; cin>>n;
n1=(int)((1+sqrt(1+8*m))/2);
cout<<Numarul maxim de noduri izolate este <<n-n1-1;}

Graful parial

Fie graful G=(X,U) i multimea V. Graful Gp=(X,V) se numete graf parial al grafului
G.
Astfel spus, un graf parial al grafului G este el nsui sau un graf care s-a obinut prin
eliminarea unor muchii(arce) din graful G.
Numrul de grafuri pariale ale unui graf cu m muchii(arce) este egal cu 2
m
.

Algoritmi pentru prelucrarea grafurilor pariale
1.Generarea tuturor grafurilor pariale ale unui graf neorientat.
Algoritmul. Se folosete metoda backtracking. n stiv se vor genera muchiile grafului
parial. Deoarece graful parial poate avea p muchii(0<=p<=m), se va apela repetat
subprogramul bt(), la fiecare apel generndu-se variantele cu p muchii. Fiecare apel al
subprogramului bt() trebuie s genereze C
p
n
de muchii(arce) din graf. La fiecare apel al
subprogramului, soluia se obine atunci cnd n stiv s-au generat cele p muchii ale
grafului parial. Evidena muchiilor este pstrat n matricea de inciden.
Implementarea algoritmului. Se realizeaz cu programul 3.Se citete din fiierul text
graf15.txt matricea de adiacen a unui graf neorientat. Pentru fiecare graf parial se
afieaz muchiile. Matricea de inciden b se obine din matricea de adiacen cu funcia
transformare(). n variabila nr se contorizeaz numrul de grafuri pariale generate. n
funcia tipar() se afieaz graful parial generat.
Programul 3
#include<iostream.h>
fstream f(graf13.txt,ios::in);
typedef int stiva[100];
int n,m,p,k,ev,as,a[10][10], b[10][20], nr;
stiva st;
void citeste()
{int i,j; f1>>n>>x;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) {f1>>a[i][j]; if(a[i][j]==1) m++;}
m=m/2; f.close();}
void transformare()
{int i,j,k=1;
for (i=1;i<=n;i++)
for(j=1;j<=n;j++) if(a[i][j]==1) {b[i][k]=1; b[j][k]=1; k++;}}
void init() {st[k]=0;}
int succesor()
{if( st[k]<m) {st[k]=st[k]+1; return 1; } else return 0; }
int valid()
{if(k<1 && st[k]<st[k-1]) return0;
for(int i=1;i<k;i++) if(st[k]==st[i]) return 0; return 1; }
int solutie() {return k==p;}
void tipar()
{int i, j; nr++;
cout<<:Graful partial <<nr<<endl; cout<<Muchiile: ;
for(i=1;i<=p;i++)
{for(j=1;j<=n;j++) if (b[j][st[i]]==1) cout<<j<< ; cout<<; ; }
void bt() {//partea fixa a algoritmului backtracking}
void main()
{citeste(); transformare();
for(p=m;p>=0;p- -) bt() ; }

2.Verificarea dac un graf Gp este graf parial al unui graf G.
Algoritmul. Se verific dac cele dou grafuri au celeai numr de noduri i dac graful
Gp nu conine muchii care nu exist n graful G.
Implementarea algoritmului. Se citesc, n programul 4, din dou fiiere text g1p.txt i
g2p.txt, informaii despre dou grafuri neorientate ( sau orientate): de pe prima linie,
numrul de noduri, i apoi, de pe urmtoarele rnduri, matricea de adiacen. Matricea de
adiacen ale celor dou grafuri sunt a1 i a2, cu dimensiunea n, respectiv m. Funcia
grafp() verific dac graful Gp este graf parial al grafului G.
Programul 4
#include<iostream.h>
fstream f1(g1.p.txt,ios::in), f2(g2p.txt,ios::in);
int m,n,a1[10][10], a2[10][10];
int grafp()
{if (m!=n) return 0;
else for (int i=1;i<=n;i++)
for(int j=1;j<=n;j++) if(a2[i][j]==1 && a1[i][j]==0) return 0;
return 1;}
void main()
{int i,j; f1>>n;
for(i=1;i<=n;i++)
for (j=1;j<=n;j++) f1>>a[i][j]; f1.close();
f2>>m;
for(i=1;i<=m;i++)
for(j=1;j<=m;j++) f2>>a2[i][j]; f2.close();
if(grafp()) cout<< este graf partial ;else cout<< nu este graf partial ;}

3.Obinerea unui graf parial Gp al unui graf G.
Algoritmul. Se elimin din graful G muchiile, n funcie de condiia impus de problem.
Reprezentarea cea mai adecvat pentru graf este matricea de adiacen, n care se atribuie
valoarea 0 elementelor a[i][j] i a[j][i], corespunztoare muchiilor [i,j] care trebuie
eliminate.
Implementarea algoritmului. Se citesc din fiierul text g3.txt, informaii despre graful
neorientat: de pe prima linie numrul de noduri n i eticheta unui nod x, i apoi, de pe
urmtoarele rnduri, matricea de adiacen a grafului. Informaiile despre graful parial
obinut se scriu n fiierul text g4.txt, astfel: pe primul rnd numrul de noduri n i
numrul de muchii m i pe urmtoarele m rnduri- muchiile, sub form de perechi de
etichete de noduri desprite prin spaiu. Cerina este s se obin subgraful prin
eliminarea tuturor muchiilor care au la extremiti un nod cu grad par i nodul x. n
vectorul v se memoreaz nodurile care au grad par. n programul 5, funcia citeste() se
folosete pentru a citi informaiile despre matricea de adiacen a grafului din fiierul
text, funcia scrie() pentru a scrie n fiierul text informaiile despre lista muchiilor
grafului parial, funcia grad() pentru a determina gradul unui nod, iar funcia
graf_partial() pentru a obine graful parial. Pentru a obine graful parial, se caut toate
muchiile care au la extremiti un nod cu gradul par i nodul x(muchiile [v[i],x] pentru
care a[v[i]][x]==1) i se elimin aceste muchii.
Programul 5
#include<iostream.h>
fstream f1(g3p.txt,ios::in), f2(g4p.txt,ios::out);
int a[20][20],n,m,x,v[10];
void citeste() {//se citeste matricea de adiacenta din fisier}
int grad(int i)
{int j,g=0; for(j=1;j<=n;j++) g+=a[i][j]; return g;}
void graf_partia()
{int i,k=0; for(i=1;i<=n;i++)
if(grad(i)%2==0) {k++; v[k]=i; }
if( a[v[i]][x]==1) {a[v[i]][x]=0; a[x][v[i]]=0; m--; }}
void scrie()
{int i,j; f2<<n<< <<m<<endl;
for(i=1;i<=n;i++)
for(j=1;j<i;j++) if(a[i][j]==1) f2<<i<< <<j<<endl;
f2.close(); }
void main() {citeste(); graf_partial(); scrie();}



Subgraful
Fie graful G=(X,U).Graful Gs=(Y,V) se numeste subgraf al grafului G dac Y
X(subgraful conine numai noduri ale grafului) i muchiile (arcele) din mulimea V sunt
toate muchiile(arcele) din mulimea U care au ambele extremiti n mulimea de noduri
Y.Se spune c subgraful Gs este indus sau generat de mulimea de noduri Y.
Un subgraf al grafului G este el nsui sau un graf care s-a obinut prin suprimarea din
graful G a unor noduri i a tuturor muchiilor(arcelor) incidente cu aceste noduri.
Exemple:
1.Pentru graful neorientat G
1
=(X
1
,U
1
),definit anterior,graful G
1s
=(Y
1
V
1
),definit astfel:
-mulimea nodurilor este Y
1
={1,2,3,5,6,7}.
-mulimea muchiilor este V
1
={[1,2],[1,3],[2,5],[6,7]}.
este subgraf al grafului G
1.

Graful G
1
Graful G
1s




Numrul de subgrafuri ale unui graf cu n noduri este egal cu

-1.

Algoritmi pentru prelucrarea subgrafurilor
1.Generarea tuturor subgrafurilor unui graf.
Algoritmul.Se folosete metoda backtracking.n stiva se genereaz nodurile
subgrafului.Deoarece subgraful poate avea p noduri,se va apela repetat subprogramul
bt(),la fiecare apel generndu-se variantele cu p noduri.Fiecare apel al subprogramului
bt() trebuie s se genereze

de noduri din graf.La fiecare apel al


subprogramului,soluia se obine atunci cnd n stiv s-au generat cele p noduri ale
subgrafului.Pentru nodurile generate n stiv se afieaz muchiile(arcele) care exist n
graf.
Implementarea algoritmului. Se realizeaz cu programul 1.Se citesc,din fiierul text
graf1.txt,matricea de adiacen a unui graf neorientat,respective,din fiierul
graf2.txt,matricea de adiacen a unu graf orientat.Pentru fiecare subgraf generat,se
afieaz numrul de noduri i muchiile (arcele).n variabil nr se contorizeaz numrul de
subgrafuri generate.n funcia tipar() se afieaz subgraful generat.
Programul 1
#include<iostream.h>
fstream f (graf1.txt,ios::in);
\\fstream f(graf2.txt,ios::in); pentru graful orientat
typedef int stiva[100];
int n,p,k,ev,as,a[10][10],nr;
stiva st;
void citete() {//se citete matricea de adiacen din fiier}
void init() {st[k]=0;}
int succesor()
{if (st[k]<n) {st[k]=st[k]+1; return 1;} else return 0;}
int valid()
{if (k>1 && st[k]<st[k-1]) return 0;
for(int i=1;i<k;i++) if (st[k]==st[i]) return 0;
return 1;}
int soluie() {return k==p; }
void tipar()
{int i,j; nr++;
cout<<Subgraful <<nr<<endl<<Nodurile: ;
for(i=1;i<=p;i++) cout <<st[i]<< ; cout<<endl;
cout<<Muchiile: ; // cout<<Arcele: ; pentru graful orientat
for (i=1;i<=p;i++)
for (j=i+1; j<=p;j++) //for (j=1;j<=p;j++) pentru graful orientat
if (a[st[i]] [st[j]]==1) cout<<st[i]<<-<<st[j]<< ;
cout<<endl;}
void bt() {//partea fixa a algoritmului backtracking}
void main()
{citeste (); for(p=n;p>=1;p--) bt();}

2.Verificarea dac un graf Gs este un subgraf al unu graf G.
Algoritmul.Se verific dac:
-numrul de noduri din graful Gs este mai mic sau cel mult egal cu numrul de noduri din
graful G;
-etichetele nodurilor din graful Gs exist printre etichetele grafului G;
-ntre nodurile din graful Gs exista muchiile dintre nodurile din graful G i numai acelea.
Implementarea algoritmului.Se folosete programul 2.Se citesc,din dou fiiere text
g1s.txt i g2s.txt,informaii despre dou grafuri neorientate(orientate):de pe prima linie
numrul de noduri i apoi de pe urmtoarele rnduri,matricea de adiacen.n fiierul
g2s.txt pe ultimul rnd,dupa matricea de adiacen,este memorat un ir de numere care
reprezint etichetele nodurilor din acest graf.Matricele de adiacen ale celor dou grafuri
sunt a1 i a2,cu dimensiunea n,respectiv m.n vectorul v se memoreaz etichetele
nodurilor celui de al doilea graf.Funcia subgraf() verific dac graful Gs este subgraf al
grafului G.
Programul 2
#include<iostream.h>
int m,n,a1[10][10],a2[10][10],v[10];
fstream f1(g1s.txt,ios::in), f2(g2s.txt,ios::in);
int subgraf()
{if (m>n) return 0;
else { for (int i=1;i<=m;i++) if (v[i]>n) return 0;
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++) if (a2[i][j]!=a1[v[i]] [v[j]]) return 0;}
return 1;}
void main()
{int i,j; f1>>n;
for(i=1;i<=n;i++)
for (j=1;j<=n;j++) f1>>a1[i][j]; f1.close();
f2>>m;
for (i=1;i<=m;i++)
for(j=1;j<=m;j++) f2>>a2[i][j];
for (i=1;i<=m;i++) f2>>v[i]; f2.close();
if (subgraf()) cout<<este subgraf ;
else cout <<nu este subgraf ;}

3.Verificarea dac dou matrici de adiacen pot reprezenta matricele de adiacen ale
unui graf i ale unui subgraf al acestuia.
Algoritmul.Matricele de adiacen ale celor dou grafuri au dimensiunea n,respective
p.Se identific graful care are ordinul mai mare (n) si gradul celuilalt graf-p(n p).Pentru
graful cu n noduri se genereaz toate matricele de adiacen ale subgrafurilor cu p noduri
i se verific dac una dintre ele este identic cu matricea de adiacen a celuilalt graf
).Generarea tuturor subgrafurilor cu p noduri se face cu metoda backtracking.n stiv se
vor genera nodurile subgrafului.
Implementarea algoritmului. Se citesc din doua fiiere text, graf_1s.txt i graf_2s.txt,
informaii despre matricele de adiacen a dou grafuri neorientate:de pe prima linie,
numrul de noduri,apoi matricea de adiacen.Se verific dac unul dintre grafuri este
subgraf al celuilalt,iar n caz afirmativ, se identific care este graful i care este
subgraful.Matricele de adiacen ale celor dou grafuri sunt a1 i a2.Variabila x se
folosete pentru a identifica relaia dintre cele dou grafuri:dac are valoarea 0,a doua
matrice de adiacen se asociaz unui posibil subgraf.Variabila logic gsit se
folosete pentru a determina dac una dintre matricele de adiacen reprezint matricea de
adiacen a unui subgraf:are valorea 0-False,dac nu este subgraf i valoarea 1-True dac
este subgraf.n matricea b se va construi matricea de adiacen a unui subgraf format cu
nodurile generate n stiva.Funcia zero() se folosete pentru a initializa cu 0 elementele
matricei b-nainte de generarea fiecrui subgraf.Funcia furnizeaz un rezultat logic:1-
true,dac matricea generata i matricea asociat unui posibil subgraf sunt egale;altfel,are
valoarea 0-false.Rezultatul acestei funcii este atribuit variabilei gsit.Subprogramul bt()
se execut att timp ct nu s-a generat o matrice de adiacen egal cu cea asociat unui
posibil subgraf(gsit==0) i se mai pot cauta soluii pentru matricea generata(k>0).
Programul 3
#include<iostream.h>
int n,p,a1[10][10],a2[10][10],b[10][10],v[10],nr,x,as,ev,k,gsit;
fstream f1(graf1_s.txt,ios::in), f2(graf2_s.txt,ios::in);
typedef int stiv[100];
stiva st;
void zero()
{for (int i=1;i<=p;i++)
for(int j=1;j<=p;j++) b[i][j]=0;}
void init() {[st[k]=0;}
int succesor()
{if (st[k]<n) {st[k]=st[k]+1; return 1;} else return 0;}
int valid()
{if (k>1 && st[k]<st[k-1]) return 0;
for (int i=1;i<k;i++) if (st[k]==st[i]) return 0;
return 1;}
int soluie() {return k==p; }
int tipar()
{int i,j; zero();
if (x==0)
{for (i=1;i<=p;i++)
for(j=1;j<=p;j++) if (a1[st[i]] [st[j]]==1) b[i][j]=1;
for (i=1;i<=p;i++)
for (j=1;j<=p;j++) if (a2[i][j]!=b[i][j]) return 0;}
else
{ for (i=1;i<=p;i++)
for(j=1;j,=p;j++) if (a2 [st[i][j]] [st[i][j]]==1) b[i][j]=1;
for (i=1;i<=p;i++)
for (j=1;j<=p;j++) if (a1[i][j]!=b[i][j] ) return 0;}
return 1;}
void bt()
void main()
{int i,j,m; f1>>n;
for (i=1;i<=n;i++)
for (j=1;j<=p;j++) f1>>a1[i][j]; f1.close();
f2>>p;
for (i=1;i<=p;i++)
for(j=1;j<=p;j++) f2>>a2[i][j]; f2.close();
if (p>n) {m=n; n=p; n=m; x=1;}else x=0;
bt();
if (gasit) if (x) cout<<prima matrice de adiacen este a subgrafului;
else cout<<a doua matrice de adiacen este a subgrafului;
else cout <<nu este subgraf ;}

I.6.2.Graf bipartit
Graful G=(X,U) se numete bipartit dac exis dou mulimi nevide de noduri A i B
care au urmtoarele proprieti: AUB=X i AB= i orice muchie (arc) din mulimea U
are o extremitate n mulimea de noduri A i o alt extremitate n mulimea de noduri B.
Exemple:
1.Graful neorientat definit n figura 35, este un graf bipartit, deoarece exist mulimile A
i B care s ndeplineasc condiiile din definiie: A={1, 3, 6, 7, 8, 10} i B={2, 4, 5, 9,
11}.Se observ c: AUB= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}= X i AB= i c fiecare
muchie u din
U ={[1,2], [1,4], [2,3], [3,4], [3,5], [5,6], [5,7], [5,8], [7,9]} are o extremitate n mulimea
A i cealalt extremitate n mulimea B:
Fig.35
Graful bipartit G=(X,U) se numete graf bipartit complet dac pentru orice nod x
i
A i
orice nod x
j
B exist o muchie (un arc) format din cele dou noduri care aparine
mulimii U: [x
i
, x
j
] U.
Exemple:
1.Graful neorientat G28 = (X28,U28) din figura 36, definit astfel: X28={1, 2, 3, 4} i U28=
{[1,2], [1,4], [2,3], [2,4]} este un graf bipartit complet deoarece exist mulimile A i B
care ndeplinesc condiiile din definiie: A={1, 3} i B= {2, 4}. Se observ c: AUB= {1,
2, 3, 4} i AB= i c fiecare nod din mulimea A este legat cu o muchie de fiecare nod
din mulimea B.

Fig.36-Graful G28

2.Graful orientat G29= (X29,U29) definit astfel: X29 ={1, 2, 3, 4} i U29={[1,2], [1,4], [2,1],
[2,3], [3,2], [4,3]} este un graf bipartit complet , deoarece exist mulimile A i B care s
ndeplineasc condiiile din definiie: A= {1, 3} si B= {2, 4}.Se observ c: AUB= {1, 2,
3, 4} i AB = i c fiecare nod din mulimea A este legat cu cel puin un arc de fiecare
nod din mulimea B.
Fig.37-Graful G29


Algoritmi pentru prelucrarea grafurilor bipartite
1.Generarea tuturor grafurilor neorientate bipartite complete cu n noduri.
Algoritmul. Problema se reduce la a genera toate submulimile care se pot obine din cele
n elemente (exceptnd mulimea iniial i mulimea vid). Numrul total de submulimi
obinute este 2
n
-2. Soluia este de a genera ntr-un vector nodurile care aparin mulimilor
A i B, astfel: dac un element are valoarea 1, nodul care are eticheta corespunzatoare
indicelui elementului aparine mulimii A; altfel, aparine mulimii B.
Implementarea algoritmului.Programul 1: funcia generare ( ) genereaz grafurile
bipartite complete. n vectorul a se genereaz nodurile mulimilor A i B. Iniial
elementele vectorului au valoarea 0. Variabila posibil se folosete pentru a verifica dac
mai exist posibiliti de generare de submulimi (are valoarea 1- true, atunci cnd mai
este posibil s se genereze submulimi).
Programul 1
#include<iostream.h>
#include<math.h>
void generare (int n)
{int a[10]= {0}, i, j, k=0, posibil=1;
while (posibil){j=n; while (j>0 &&a[j]==1) {a[j]=0; j--;}
if (j==0) posibil=0;else {a[j]=1; k++;
if (k<= pow(2,n) 2)
{cout<< graful <<k<<endl<<multimea A: ;
for (i=1; i<=n; i++) if (a[i]) cout<<i<< ;
cout<<multimea B: ;
for (i=1; i<=n; i++) if (!a[i]) cout<<i<< ;
cout<<endl ;
cout<<muchiile sunt: ;
for (i=1; i<=n; i++)
if (a[i]==1)
for(j=1; j<=n; j++)
if (a[j]==0 && i!=j)
cout<<[<<i<< , <<j<<] ;
cout<<endl; }}}}
void main ( ) {int n; cout<<numar de noduri= ; cin>>n; generare (n); }

2.Verificarea unui graf dac este bipartit.
Algoritmul. Pentru a verifica dac graful este bipartit, se genereaz mulimile de noduri A
i B pn cnd aceste mulimi ndeplinesc condiia unui graf bipartit, sau pn cnd s-au
generat toate mulimile i nici una dintre variante nu a ndeplinit condiia pentru graful
bipartit.Graful este bipartit dac ntre orice pereche de elemente din cele dou mulimi
(x,y), cu x A i y B exist muchie care s le lege n graf ([x,y] U).Pentru generarea
mulimilor de noduri A i B se pot folosi dou variante:
Varianta 1. n programul 2 se genereaz ntr-un vector toate submulimile care se pot
obine din cele n etichete de noduri (exceptnd mulimea iniial i mulimea vid) i se
verific dac nodurile aparinnd celor dou mulimi generate pot fi mulimile unui graf
bipartit.
Implementarea algoritmului. Se citesc din fiierul text gb.txt informaii despre un graf
neorientat (numrul de noduri i matricea de adiacen). Funcia bipartit ( ) verific dac
graful este bipartit furniznd un rezultat logic. Elementele vectorului x n care se
genereaz mulimile A i B sunt iniial 0. Variabila gasit se folosete pentru a verifica
dac s-au gasit cele dou mulimi de noduri corespunztoare unui graf bipartit (are
valoarea 1 true, atunci cnd s-au gsit).
Programul 2
#include<fstream.h>
#include<math.h>
fstream f (gb.txt ,ios::in);
int a[10] [10], n;
void citeste ( ) {//citete matricea de adiacen din fiier}
int bipartit ( )
{int x[10]={0}, i, j, m, k=0, posibil=1, gasit=0;
while (posibil && !gasit)
{m=n;
while (m>0 && x[m]==1) {x[m]=0; m --;}
if (m==0) posibil=0;
else
{x[m]=1; k++;
if (k<=pow (2,n) 2)
for (i=1, gasit=1;i<=n && gasit; i++)
for (j=1; j<=n && gasit; j++)
if (a[i] [j]==1)
if (x[i]==1 && x[j]==1)| |(x[i]==0 && x[j]==0)) gasit=0; }}
return gasit; }
void main ( )
{citeste ( );
if (bipartit ( ) ) cout<<este bipartit ;
else cout<<nu este bipartit;}
Varianta 2. Elementele mulimilor A i B se genereaz separat, n doi vectori. Pentru
generarea mulimii A se folosete metoda backtracking (etichetele nodurilor mulimii A se
genereaz n stiv. Funcia bt ( ) este apelat de n-1 ori pentru a genera n stiv cele p
elemente ale multimii (1pn-1). Multimea B este format din nodurile grafului care nu
se gsesc n mulimea A.
Implementarea algoritmului. Matricea A este matricea de adiacen a grafului, iar n
vectorii a i b se genereaz elementele mulimilor A i B. n funcia tipar ( ) se copiaz
coninutul stivei n vectorul a i se scriu n vectorul b etichetele nodurilor care nu sunt n
vectorul a. Pentru a identifica etichetele nodurilor care nu sunt n vectorul a se folosete
variabila logic gasit. Tot n aceast funcie se verific dac aceste mulimi corespund
unui graf bipartit, astfel: se verific, pentru toate elementele celor doi vectori, daca
muchiile generate cu un nod din vectorul a i un nod din vectorul b sunt muchii n graf.
n caz afirmativ, se verific dac muchiile astfel generate sunt toate muchiile grafului.
Variabila nr se folosete pentru a numra muchiile formate cu nodurile din cei doi
vectori, iar variabila logic este pentru a verifica dac graful este bipartit (are vaolarea 1-
true, dac numrul de muchii gsite este egal cu numrul total de muchii ale grafului m).
#include<fstream.h>
frstream f (gb.txt ,ios::in) ;
typedef int stiva [100];
int n, k, ev, as, A[10] [10], b[10], a[10], m, este, p;
stiva st;
void citeste ( )
{int i, j; f>>n;
for (i=1; i<=n; i++;
for(j=1; j<=n; j++) {f>>A[i] [j]; m=m+ A[i] [j];} f.close ( ); m=m/2;}
void init ( ) {st[k]=0; }
int successor ( )
{ if (st[k]<n) {st[k]=st[k]+1; return 1;} else return 0;}
int valid ( )
{if (k>1 && st[k]<st[k-1]) return 0;
for (int i=1; i<k; i++) if (st[k]==st[i]) return 0; return 1;}
int solutie( ) {return k==p;}
void tipar ( )
{int i, j, q=0, gasit, nr=0;
for (int i=1; i<=p; i++) a[i]=st[i];
for (i=1; i<=n; i++)
{for (j=1, gasit=0; j<=p && !gasit; j++) if(a[j]==i) gasit=1;
if (!gasit) {q++; b[q]=i; }}
for (i=1; i<=p; i++)
for (j=1; j<=q; j++) if (A[a [i] ] [b [j] ]==1) nr++;
if (nr==m) este=1; }
void bt ( ) {// partea fix a algoritmului backtracking}
void main( ) {citeste ( );
for (p=1; p<= n-1 && !este; p++) bt ( );
if (este) cout<<este bipartit;
else cout<<nu este bipartit; }


I.6.3. Graf hamiltonian

ntr-un graf G=(X,U), se numete lan hamiltonian lanul elementar care conine toate
nodurile grafului.
Un lan este hamiltonian dac pornete de la un nod oarecare i parcurge o singur dat
toate nodurile grafului.
Lanul hamiltonian n care nodul iniial coincide cu nodul final se numete ciclu
hamiltonian.
Ca ntr-un graf s existe un ciclu hamiltonian este necesar ca pe lng un lan
hamiltonian s mai existe i o muchie care s lege primul nod al lanului de ultimul nod al
lanului.
Un graf care conine un ciclu hamiltonian se numete graf hamiltonian.
Un graf hamiltinoan este un graf n care -pornind de la un nod oarecare-se pot parcurge o
singur dat toate nodurile grafului,revenind la nodul iniial.
Graful G
30
din figura 39 conine ciclul hamiltonian C={1,2,3,4,5,1}.
Un graf hamiltonian nu poate conine noduri izolate.
Graful complet K
n
este hamiltonian.
Fig.39

Orice problem la care soluia este de a gsi un traseu- care pornete dintr-un anumit
punct, trebuie s treac prin puncte precizate, cu revenire la punctul de pornire- se rezolv
prin gsirea unui ciclu hamiltonian.


De exemplu:
- firm de mesagerie trebuie s distribuie zilnic colete la mai multe adrese.Maina
care distribuie aceste colete pleac de la sediul firmei, ajunce la mai multe puncte
din ora i revine la sediul firmei.Legtura direct dintre dou puncte este
caracterizat prin distana msurat n kilometri (costul asociat fiecrei muchii).
Trebuie s se gseasc traseul de lungime minim pe care trebuie s-l parcurg
maina.
- persoan dorete s fac un circuit prin ar i s viziteze mai multe puncte
turistice, plecnd din localitatea de domiciliu i ntorcndu-se n aceeai localitate.
Legtura direct dintre dou puncte turistice este caracterizat prin distana
msurat n kilometri (costul asociat unei muchii). Trebuie s se gseasc circuitul
turistic de lungime minim.
- persoan dorete s viziteze mai multe cabane,ntorcndu-se la locul de plecare.
Legtura direct dintre dou cabane este caracterizat prin timpul necesar
parcurgerii traseului de munte (costul asociat fiecrei muchii). Trebuie s se
gseasc circuitul de vizitare a cabanelor care s se fac n timp minim.
Dac graful G=(X,U) este un graf cu mai mult de dou noduri (n>=3) i gradul fiecrui
nod x X satisface condiia d(x)>=n/2, atunci graful G este hamiltonian.

Algoritm pentru parcurgerea unui graf hamiltonian
Algoritmul.Pentru a determina dac un graf este hamiltonian se verific dac exist un
ciclu hamiltonian.Este suficient s se caute lanurile elementare care pornesc din nodul
cu eticheta 1 i se nchid n acest nod. Se poate folosi fie metoda backtracking, fie metoda
parcurgerii n lime a grafului. Prin aceste metode se pot determina i toate ciclurile
hamiltoniene, dac exist, astfel: se caut toate ciclurile elementare care, pornind dintr-un
nod, parcurg toate celelalte noduri ale grafului i se nchid printr-o muchie cu nodul de
pornire.
Implementarea algoritmului. Se folosete programul 1:se citete din fiierul graf_h.txt
matricea de adiacen a unui graf neorientat. Dac graful este hamiltonian, se afieaz
ciclurile hamiltoniene gsite. Dac nu exist nici o soluie, se afieaz un mesaj de
informare. Pentru generarea lanurilor elementare se folosete metoda backtracking.
Nodurile lanului elementar vor fi generate n stiv. Funcia citeste( ) se folosete pentru a
citi matricea de adiacen n fiier. Variabila este se folosete pentru a verifica dac s-a
gsit un ciclu hamiltonian pornind din nodul cu eticheta 1 (are
valoatea 0- false, dac nu s-a gsit nici un ciclu hamiltonian).
Programul 1
#include<fstream.h>
typedef stiva [100] ;
int a[20] [20], n, k, as, ev, este=0 ;
stiva st ;
fstream f(graf h.txt, ios::in) ;
void citeste ( )
void init ( ) {st[k]=0 ;}
int succesor ( )
{if (st[k]<n) {st[k]=st[k]=+1 ; return 1 ;} else return 0 ;}
int valid ( )
{if (k>1 && a[st[k-1]] [st[k]]==0) return 0 ;
for (int i=1; i<k; i++) if(st[k]==st[i]) return 0 ;
return1;}
int solutie ( ) {return a[st[k]] [1]==1 && k==n;}
void tipar ( )
{for (int i=1, este =1; i<=n; i++) cout<< st[i]<< , ; cout << st[1]<<endl;}
void bt ( )
void main ( ) {citeste ( ); st[1]=1; bt ( );
if (!este) cout<<Graful nu este hamiltonian ; }

I.6.4. Graful eulerian
ntr-un graf G=(X,U),se numete lan eulerian lanul care conine toate muchiile
grafului,fiecare muchie fiind prezent o singura dat.
Un lan este eulerian dac porneste de la un nod oarecare i parcurge o singur dat
toate muchiile grafului( este un lan simplu care parcurge toate muchiile grafului).Lanul
eulerian n care nodul iniial coincide cu cel final se numete ciclu eulerian.
Ca ntr-un graf s existe un ciclu eulerian este necesar ca ,pe lng un lan eulerian, s
mai existe i o muchie care s lege primul nod al lanului de ultimul nod al lanului,i acea
muchie s nu mai fi fost parcurs.Un graf care conine un ciclu eulerian se numete graf
eulerian.Un graf eulerian este un graf n care, pornind de la un nod oarecare se pot
parcurge o singur dat toate muchiile grafului,revenind la nodul iniial.
Graful din figura alturat conine ciclul eulerian C=[1,4,6,7,4,5,7,8,3,2,8,5,2,1].
Un graf eulerian nu poate conine noduri izolate.
Pentru ca un graf s poat fi fcut eulerian prin adogarea muchiilor trebuie s fie
indeplinite urmtoarele condiii:
- Dac numarul de noduri este par,s nu existe noduri cu gradul maxim;
- Numrul de noduri cu grad impar s fie par.




Algoritm pentru parcurgerea unui graf eulerian
Pentru a implementa graful se folosete matricea de adiacena a si vectorul g n care se
memoreaz gradul fiecarui nod care se calculeaz cu functia grad() .
Algoritmul care determin dac un graf este eulerian verific dac graful ndeplinete
condiiile :
- Nodurile izolate. Se verific dac graful are sau nu noduri izolate. Dac are
noduri izolate se consider c graful nu este eulerian .n implementarea
algoritmului se folosete functia izolat() care testeaz gradul nodurilor i
furnizeaz un rezultat logic : true (1) dac cel puin un nod are gradul 0 i
false (1) dac nici un nod nu are gradul 0.
- Gradul nodurilor. Se verific dac gradul fiecrui nod este par.n
implementarea algoritmului se folosete funia grad_par () care furnizeaz un
rezultat logic: false (0) dac cel puin un nod are gradul impar i true (1) dac
nici un nod nu are gradul impar.
- Conexitatea.Se verific dac gradul este conex.Pentru aceasta se va parcurge
graful n adncine i se verific dac ramn noduri nevizitate.n
implementarea algoritmului se folosete vectorul vizitat pentru a ine
evidena nodurilor vizitate.Conexitatea se verific prin funcia conex () care
furnizeaz un rezultat logic: false (0) dac cel puin un nod a fost vizitat su
true (1) dactoate nodurile au fost vizitate.
Pentru testarea condiiilor necesare ca un graf sa fie eulerian se folosete variabila
eulerian care are valoare logica : false(0) dac graful nu este eulerian i true (1) dac
graful este eulerian.
Dac graful este eulerian se poate determina un cilcu eulerian. Construirea ciclului
eulerian se face astfel:
PAS.1 Se pornete dintr-un nod oarecare din graf i se constriete din aproape n aproape
ciclul C, pe muchii incidente care exista in graf,scznd gradele nodurilor
prin care trece i eliminnd muchiile.
PAS.2 Ct timp mai exist muchii care nu fac parte din ciclul C execut: se alege un nod
din ciclul C pentru care mai exista muchii incidente care nu fac parte din
ciclul C, se construiete ciclul C
1
si se concateneaz ciclul C
1
la ciclul C.
Soluia se va obine ntr-un vector c care conine nodurile parcurse care au fost adugate
la ciclul eulerian.Vectorul c1 se folosete pentru extinderea ciclului eulerian.Se mai
folosesc urmtoarele variabile de memorie:
- n numarul de noduri i m - numarul de muchii ;
- i,j,k contori pentru parcurgerea matricei de adiacena i a vectorilor folosii;
- q variabila n care se pastreaz nodul de la care ncepe ciclul c1;
- p variabila n care se pastreaz lungimea logic a vectorului c1.
Algoritmul pentru determinarea ciclului eulerian este urmtorul:
PAS1.Se citesc valorile pentru variabilele de memorie n i m i matricea de adiacena a.
PAS2.Se verific dac graful este eulerian, adic dac ndeplinete condiia s nu aiba
noduri izolate nodurile s aib grade pare i s fie conex.
PAS3.Dac graful nu este eulerian atunci se afieaz mesajul Graful nu este eulerian i
se termin algoritmul ; astfel se scrie mesajul Graful este eulerian i se
trece la pasul 4 pentru a determina un ciclu eulerian.
PAS4.Se pleac dintr-un nod oarecare.
PAS5.Execut urmtorii pai pentru a construi n vectorul c un prim ciclu prin
parcurgerea din aproape n aproape a muchiilor grafului, pornind de la
nodul cu eticheta j egal cu 1:j=1
PAS6. Ct timp nu s-a gsit o muchie ntre nodul curent k din coada c (c[k]) i un
alt nod j din graf (j<=n) execut:
PAS7. Dac exist o muchie ntre nodul k din coada c (c[k]) i un alt nod j din
graf (a[c[k]][j]==1), atunci se trece la pasul 8 ; altfel se trece la pasul 11.
PAS8. Se adaug nodul j la coada c (k=k+1;c[k]=j).
PAS9. Se micoreaz cu o unitate gradul celor dou noduri parcurse (g[i]--;
g[c[k-1]]--;).
PAS10. Se terge din matricea de adiacen muchia parcurs (a[c[k]][j]=0;
a[j][c[k]]=0;).
PAS11. Se trece la urmtorul nod prin incrementarea lui j (j=j+1) i se revine la
pasul 6.
Pn cnd nodul curent din coada c (c[k]) este diferit de nodul de pornire.
PAS12.Ct timp mai exista muchii care nu au fost incluse in ciclu (k-1<m)execut:
PAS13. Se caut n coada c un nod i de plecare pentru ciclul c1 adic un nod
pentru care s mai existe muchii incidente cu el care nu au fost parcurse
(grad[c[i]]>0).
PAS14. Se iniializeaz cu acest nod ciclul c1 (c1[1]=c[i]) i se memoreaz acest
nod n variabila q.
PAS15. Se construiete un nou ciclu parcurgnd din algoritm pentru coada c1 de
la pasul 5 pn la pasul11.Acest ciclu va avea p elemente .
PAS16.Se concateneaz ciclul c1 cu ciclul c astfel: mai ntai se deplaseaz elementele din
vectorul c ncepnd cu pozitia q cu p poziii spre dreapta dup care se
intercaleaz ntre poziia q i poziia q+p elementele vectorului c1.
PAS17.Se afieaz elementele vectorului c.
Programul 1
#include<fstream.h>
typedef stiva[20];
int n,a[20][20],vizitat[20],vf,k,m,g[20],p=1,c[20],v1[20];
stiva st;
fstream f(graf_e.txt,ios::in);
void citeste() {//se citeste matricea de adiacenta}
void init(int i) {vf=1; st[vf]=i;vizitat[i]=1}
int este_vida() {vf++; st[vf]=i; vizitat[i]=1}
void elimin(0 {vf--;}
void prelucrare()
{int i=1; k=st[vf];
while(i<=n && (a[i][k]==0 || (a[i][k]==1 && vizitat [i]==1))) i++;
if(i==n+1) elimin(); else {p++; adaug(i);}}
int conex(0
{k=1; init(k);
while(!este vida()) prelucrare();
return(p==n);}
void grad()
{for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) if (a[i][j]==1) {g[i]++;m++;} m=m/2;}
int izolat()
{for(int i=1;i<=n;i++) if (g[i]==0 return 1;
return 0;}
{for(int i=1;i<=n;i++) if (h[i]%2==1) return 0;
return 1;}
void ciclu()
{int i,j,k=1,p,q,gasit;
c[1]=1;
do for(j=1,gasit=0;j<=n && !gasit;j++)
if ( a[c[k]][j]==1)
{k=k+1;c[k]=j;a[c[k-1]][j]=0;a[j][c[k-1]]=0;g[j]--;g[c[k-1]]--;gasit=1;}
while(c[k]!=1);
while(k-1<m)
{for(i=1,q=0;i<=k-1 && q==0; i++)
if (g[c[i]]>0) c1[1]=c[i];q=i;}
p=1;
do for (j=1,gsit=0;j<=n && !gasit;j++)
if (a[c1[p]][j]==1)
{p=p+1;c1[p]=j;a[c1[p-1]][j]=0; a[j][c1[p-1]]=0; g[j]--; g[c1[p-1]]--;gasit=1;}
while( c1[p]!=c1[1]);
for (j=k;j>=q;j--) c[j+p-1]=c[j];
for (j=1;j<=p-1;j++) c[j+q]=c1[j+1];
k=k+p-1;}}
void main()
{int eulerian; citeste ();grad ();
eulerian=!(izolat()) && grad_par() && conex();
if(!eulerian) cout<<graful nu este eulerian;
else {cout<<graful este eulerian<<endl;
ciclu(); cout<<ciclul eulerian este: ;
for (int i=1;i<=m+1;i++) cout<<c[i];}}

I.6.5.Graful turneu
Un graf orientat n care, ntre oricare dou noduri exist un
singur arc i numai unul, se numete graf turneu.Arcul dintre dou
noduri poate avea oricare dintre cele dou orientri.
Graful turneu este un graf complet.
Orice graf turneu conine un drum elementar care trece prin toate nodurile grafului.
Pentru orice nod x
i
dintr-un graf turneu cu n noduri , d
+
(x
i
)+d
-
(x
i
)=n-1.




Studiu de caz
Scop:exemplificarea unei aplicaii n care soluia problemei este un graf turneu.
Enunul problemei : Pentru un concurs hipic s-au montat n obstacole . Pentru a parcurge
traseul concursului, clreii pot ncepe cu orice obstacol , trebuie s treac peste toate
obstacolele , iar de la un obstacol la altul pot circula ntr-un singur sens , stabilit inaintea
concursului. S se precizeze ce trasee poate urma un clre.
Obstacolele formeaza nodurile unui graf orientat , n care fiecare dou noduri sunt legate
de un arc.Deoarece drumul dintre dou obstacole nu poate fi parcurs dect ntr-un singur
sens,nseamn c graful concursului este un graf turneu.A determina un traseu pentru
parcurgerea obstacolelor , nseamn a determina n graful turneu un drum elementar ca
trece prin toate nodurile grafului.

Algoritmul pentru parcurgerea grafului turneu
Pentru a determina drumul elementar care trece prin toate nodurile grafului se poate
folosi fie metoda backtracking, fie urmtorul algoritm, prin care se extrag cele n noduri
ale drumului ntr-un vector D.n acest algoritm,se iniializeaz vectorul cu nodurile cu
etichetele 1 i 2 sau 2 i 1, n funcie de arcul care exist [1,2] respectiv[2,1], dup care se
insereaz n vectorul drumului i celelalte noduri, n funcie de arcele care exist n graf:
PAS1. Dac exist arcul[1,2], atunci D[1]=1 i D[2]=2 ; altfel , D[1]=2 i D[2]=1
PAS2. Se iniializeaz lungimea drumului,m, cu 2.
PAS3. Pentru nodurile cu eticheta i de la 3 pn la n execut:
PAS4. Dac exist arcul [i,1],atunci poziia de inserare k a nodului i este 1 i se trece la
pasul 7;altfel,pentru a parcurge nodurile din drum se iniializeaz indicele j cu valoarea 1
i se trece la Pasul 5.
PAS5. Ct timp nu s-a ajuns la captul vectorului D i nu s-a gsit poziia de inserare a
nodului i execut:
PAS6. Dac exist arcul ntre nodul cu indicele j din drum i nodul i i exist i
arcul ntre nodul i i nodul cu indicele j+1 din drum , atunci poziia de inserare k este
j+1;altfel,se trece la urmtorul nod din drum prin incrementarea variabilei j i se revine la
pasul 6.
PAS7. Se deplaseaz elementele vectorului din poziia k spre dreapta.
PAS8. Se insereaza nodul i n poziia k.
PAS9. Se incrementeaz lungimea m a drumului D i revine la pasul 3.
Implementarea algoritmului.Se realizeaz programul 2:informaiile despre graful
neorientat se gsesc n fiierul graf_t.txt pe prima linie numrul de noduri , apoi matricea
de adiacen. Nodurile drumului elementar vor fi generate n vectorul D. Se folosesc
urmtoarele funcii: citete() pentru a citi matricea de adiacen din fiier, generare()
pentru a genera vectorul D i afiare() pentru a afia drumul elementar gsit.n funcia
generare() se folosesc urmtoarele variabile locale: i-pentru eticheta nodului care se
adaug la drum,j-pentru a cuta eticheta nodului dup care se insereaz n drum nodul cu
eticheta i,m-pentru lungimea drumului la un moment dat i gasit-pentru a ti dac s-a
gsit pozitia de inserare a nodului i n vector .
Programul 2
#include<fstream.h>
int n,a[10][10],D[10];
fstream f(graf_t.txt, ios::in);
void citeste() {// se citeste matricea de adiacenta}
void generare()
{int i,j,k,m=2,gasit;
if(a[1][2]==1) {D[1]=1 ; D[2]=2;}
else {D[1]=2; D[2]=1;}
for(i=3;i<=n;i++)
{if( a[D[1]]==1) k=1;
else
{for (j=1;gasit=0;j<=n && !gasit; j++)
if( a[D[j]][i]==1 && a[i][D[j+1]]==1) gasit=1; k=j+1;}
for (j=m+1;j>k;j--) D[j]=D[j-1]; D[k]=i;m++;}}
void afisare()
{for (int i=1;i<=n;i++) cout<<D[i];}
void main()
{citeste();
generare();afisare();}

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