Sunteți pe pagina 1din 38

Liceul Teoretic Dunarea

Galati

Grafuri orientate

Elev:Lepdatu Alexandru

Profesor indrumator

Clasa a-XII-a E

Burlacu Ctlina

PROMOTIA 2015
1

CUPRINS

1. Motivatia lucrarii....................................................................3
2. Grafuri orientate-notiuni de baza...........................................4
a) Notiunea de graf orientat..................................................4
b) Definitie............................................................................6
3. Graful unui varf......................................................................6
a) Multimile si ................................................................6
4. Graf partial si subgraf............................................................7
5. Reprezentarea grafurilor orientate.........................................8
6. Matricea de adiacenta............................................................9
a) Citirea de la tastatura si afisarea matricei de
adiacenta.............................................................................9
b)Citirea matricei de adiacenta dintr-un fisier text..............11
c)Construirea matricei de adiacenta prin citirea
arcelor de la tastatura....................................................11
d)Determinarea gradului exterior si a gradului
interior al unui nod oarecare x......................................13
7. Matricea varfurilor-ace .......................................................16
8. Listele vecinilor...................................................................18
9. Reprezentarea grafului ca un vector de muchii...................19
10.
Nodurile izolate intr-un graf
orientat..................................19
11.
Celebritate..................................................................22
12.
Interpretarea
datelor............................................................23
13.
Drumuri si circuite in grafuri
orientate...............................25
14.
Matricea
drumurilor............................................................27
15.
Algoritmul Roy-Warshall de determinare a matricei
drumurilor...........................................................................28
16.
Bibliografie.........................................................................35

Motivatia lucrarii
Un graf este o submultime de obiecte (numite noduri)
legate intre ele printr-o multime de muchii carora le pot fi
atribuite directii (in acest caz, se spune ca graful este
orientat). Vizual, un graf poate fi reprezentat ca o multime
de puncte legate intre ele prin linii (de obicei curbe).
Grafurile au fost studiate intensiv de numerosi
matematicieni si fizicieni precum Cayley, pe care l-au
interesat aplicatiile lor in chimia organica, sau Kirchhoff,
care a studiat aceasta categorie pornind de la studiul
retelelor electrice.
Grafurile au o importanta imensa in informatica, de
exemplu: in unele probleme de sortare si cautare
elementele multimii pe care se face sortarea sau cautarea
se pot reprezenta prin noduri intr-un graf; schema logica a
unui program se poate reprezenta printr-un graf orientat in
care o instructiune sau un bloc de instructiuni este
reprezentat printr-un nod, iar muchiile directionate
reprezinta calea de executie; in programarea orientata pe
obiecte, ierarhia obiectelor (claselor) unui program poate
fi reprezentata printr-un graf in care fiecare nod reprezinta
o clasa, iar muchiile reprezinta relatii intre acestea
(derivari, agregari).
De asemenea m-a captivat acest capitol al informaticii
si de aceea am ales aceasta tema.

2.Grafuri orientate noiuni de baz


a) Noiunea de graf orientat
Un exemplu de graf orientat este reeaua de strzi a
unui ora. Strzile sunt muchii n graf, iar interseciile
reprezint vrfurile grafului. ntruct mergnd pe jos ne
putem deplasa pe orice strad n ambele sensuri, vom
spune c din punctul de vedere al pietonilor, graful
unui ora este neorientat.
Cu

totul

altfel

stau

lucrurile

ceea

ce

privete

conductorii auto, pentru c n orice ora exist strzi


cu sens unic. Pentru un ofer strzile trebuie s
primeasc n graf o anumit orientare. Desigur c acele
strzi pe care se poate circula n ambele sensuri vor
primi orientare dubl. Am ajuns astfel la noiunea de
graf orientat.

Numim graf orientat, o pereche ordonat


de mulimi G=(X,U), unde:
X este o mulime finit i nevid numit
mulimea nodurilor (vrfurilor);
U

este

mulime

format

din

ordonate de

perechi
elemente

ale lui X, numit mulimea arcelor (muchiilor)

Observaii:
Prin

noiunea

de

perechi

ordonate nu trebuie s nelegem

U1

c o muchie este mai mare dect

alta, ci pur i simplu c facem


deosebire

ntre

muchie

U2
2

de

U3

forma (x,z) i o alta de forma


(y,x). Cu alte cuvinte muchiile
sunt difereniate prin ordinea de
scriere a simbolurilor.

U5
U4
3
U6
U7

Arcul (x,y) nu este tot una cu

Figura1

arcul (y,x).

Exemplu:
Pentru graful G=(X,U) din figura 1 avem: X={1, 2, 3, 4}
i U={u1, u2, u3, u4, u5, u6, u7,}= {(1,1), (2,1), (3,2),
(2,3), (2,4), (3,4), (3,4)}

arc va fi de forma u= (x,y), unde x se numete


extremitate iniial, iar y se numete extremitate final
a arcului. Cu alte cuvinte, arcul iese din nodul x i intr
n nodul y. La fel ca la grafurile neorientate, vom
spune c nodurile x i y sunt adiacente, iar arcul u i
nodul x sunt incidente (la fel arcul x i nodul y). Nodul y
se numete succesor al lui x, iar nodul x se numete
predecesor al lui y. Un arc de forma (x,x), care iese din
nodul x i intr tot x, se numete bucl.

Exemplu:
n graful din figura 1, avem bucla (1,1).
ntr-un graf putem avea dou sau mai multe arce
identice.

Exemplu :
n graful din figura 1, exist dou arce identice, u6 = u7
= (3,4)

b) Definiie
Se numete p-graf, un graf orientat n care numrul
arcelor identice este mai mic sau egal cu o valoare
dat p.
n cele ce urmeaz vom analiza numai 1-grafuri fr
bucle.

3. Gradul unui vrf


a) Mulimile i

Gradul exterior al unui vrf x, notat d*(x), reprezint


numrul arcelor care ies din nodul x, adic numrul
arcelor de forma (x,z) U.
Analog, se definete gradul interior al unui vrf x, notat
d-(x), ca fiind numrul arcelor care intr n nodul x (de
forma (y,x) U).

Exemplu:
n graful reprezentat n figura 1, pentru nodul x=2,
avem:
d*(2) =3 exist trei arce care ies din nodul 2, i
anume : u2=(2,1), u4=(2,3) i u5 = (2,4).
d-(2) =1 n nodul 2 intr un singur arc, n spe arcul
u3=(3,2).

Se mai definesc urmtoarele mulimi:


x y X x, y U

mulimea

nodurilor

ce

constituie

extremiti finale ale arcelor care pleac din nodul x. Pe


scurt, mulimea succesorilor lui x;
x y X y, x U

mulimea

nodurilor

ce

constituie

extremiti iniiale ale arcelor care pleac din nodul x.


Pe scurt, mulimea predecesorilor lui x;

Exemplu:
n graful din figura 1, pentru nodul x=2, avem:
- +(2) = {1,3,4} urmare a faptului c muchiile care
pleac din nodul 2 sunt (2,1), (2,3) i (2,4), putem
spune c mulimea succesorilor nodului 2 este {1,3,4}.
- -(2) = {3} n nodul 2 intr doar muchia (3,2), deci
mulimea predecesorilor lui 2 conine doar nodul 3.

+(x) = {u = (x,y)| u U} mulimea arcelor care ies


din nodul x;
-(x) = {u = (y,x)| u U} mulimea arcelor care intr
n nodul x;

Exemplu:
n graful din figura 1, pentru nodul 2, avem:
+(x) = {(2,1), (2,3), (2,4)}, -(x) = {(3,2)}

4. Graf parial i subgraf


Fie graful G = (X,U). Un graf parial al lui G, este un graf
G1= (X,V), cu

V U

. Altfel spus, un graf parial G1 al lui

G, este chiar G, sau se obine din G pstrnd toate


vrfurile i suprimnd nite muchii.
Fie graful G = (X,U). Un graf parial al lui G, este un graf
G1= (Y,T), unde V X i T U , iar T va conine numai
muchiile care au ambele extremiti n Y. Altfel spus, un
graf parial G1 al lui G, se obine din G eliminnd nite
vrfuri i pstrnd doar acele muchii care au ambele
extremiti n mulimea vrfurilor rmase.

Exemplu:
Se consider graful G = (X,U) din figura 2, n care X =
{1,2,3,4,5,6} i U={u1, u2, u3, u4, u5, u6, u7}.
Construim

graful

parial

G1

(X,V),

unde

{1,2,3,4,5,6} i V = { u2, u3, u4, u6, u7} (figura 3) din


graful G au fost eliminate arcele u1 i u5.

Construim subgraful G2 = (Y,T), unde Y = {3,4,5,6} i T


= {u4, u5, u6, u7} (figura 4) din graful G au fost
eliminate nodurile 1 i 2 precum i arcele u1, u2 i u3
care au o extremitate n afara
u2

1
u1
u4

u2

u3

5
u7

2
u3

u4

u5

mulimii nodurilor

u4

5
u7

u6

6
Figura 2

5
u7

u6

u5

u6
6

Figura 4
Figura 3

rmase.

5. Reprezentarea grafurilor orientate


Considerm un graf orientat G= (X,U) cu m arce i n
noduri.
Cele

mai

cunoscute

forme

de

reprezentare

sunt:

matricea de adiacen, matricea vrfuri arce, matricea


drumurilor i listele vecinilor.

6. Matricea de adiacen
Are

aceeai

semnificaie

ca

cazul

grafurilor

neorientate: fiecare element a[i,j], cu i,j {1,2,...,n},


este: 1 dac exist arcul (i,j), respectiv 0 n caz contrar.

Datorit orientrii, aa cum am mai spus, arcul (i,j) nu


este totuna cu arcul (j,i). Prin urmare, a[i,j] a[j,i].
Aadar matricea de adiacen nu mai este simetric
fa de diagonala principal, aa cum se ntmpla n
cazul grafurilor neorientate.

Exemplu:
Pentru

graful

G=(X,U)

din

figura

5,

matricea

de

adiacen este:
coloana

A=

Aplicaie:
a)Citirea de la
afiarea
adiacen

1
4
Figura 5

tastatur

matricei

de

Prin citirea matricei de adiacen de la tastatur, putem


memora arcele existente ntre nodurile unui graf. n
cazul grafurilor neorientate, citeam doar poriunea de
deasupra diagonalei principale n matrice, deoarece

10

matricea este simetric. Acum trebuie s citim toate


elementele matricei.
Avem de-a face cu algoritmii banali de citire i afiare a
unei matrice cu n linii i n coloane (unde n este numrul
de noduri) n dou cicluri for, deci nu considerm c mai
sunt necesare alte explicaii. Prezentm n continuare
procedurile citire_matrice i afiare_matrice.
int citire_matrice() //citete matricea de adiacen a de
la tastatur
int

citire_matrice()

//citete

matricea

de

adiacen a de la tastatur
{int i,j;
cout<<Nr. Noduri; cin>>n;
for(i=1;i<=n;i++)
{for(j=1;j<=n;i++)
{cout<<[<<i<<<<<<j<<]=);
cin>>a[i][j];}}}

int

afiare_matrice()

//afieaz

matricea

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

Aplicaie:
b) Citirea matricei de adiacen dintr-un fiier text
11

de

Aceasta este absolut similar cu cea prezentat la


grafuri neorientate, unde a fost explicat pe larg. De
fapt, este vorba despre algoritmul de citire a unei
matrice oarecare dintr-un fiier text. Plecm de la
presupunerea

fiierul

conine

pe

primul

rnd

valoarea lui n, apoi pe fiecare din urmtoarele n rnduri


elementele unei linii a matricei separate de spaii.
void

cit_matr_fis()

matricea

de

//citete

adiacenta

numrul
//din

de

fiierul

noduri

si

text

cu

descriptorul f
{int i,j;
char nume_fis;
{
Cout<<Dai numele fiierului ; cin>>nume_fis;
Cin>>i>>j;
{for(i=1;i<=n;i++)
{
{for(j=1;j<=n;i++)
Cin>>f;
}
end;

Aplicaie:
c)Construirea matricei de adiacen prin citirea arcelor de la
tastatur
Se citesc de la tastatur m perechi de numere ntregi de
forma (x,y) reprezentnd extremitile celor m arce ale

12

grafului, i se construiete matricea de adiacen a, cu


n linii i n coloane.
Mai nti citim m i n (numrul de arce respectiv
numrul de noduri), i iniializm toat matricea de
adiacen cu 0, n dou cicluri for. Apoi, ntr-un alt ciclu
for, cu k de la i la m, citim cele m perechi de ntregi
(x,y).
Citirea fiecrei perechi (x,z) se face cu validare: repet
citirea lui x i y pn cnd ambele valori sunt n
intervalul [1,n].
do
cin>>x;cin>>y;
while (x>=1) || x(<=n)|| (y>=1) || (y<=n) || (x<>y);
Pentru fiecare (x,y), marcm n matricea de adiacen
existena arcului (x,y), prin atribuirea a[x,y]:=1. Spre
deosebire de grafurile neorientate, nu se mai face i
atribuirea a[y,x]:=1, deoarece arcul (x,y) nu e identic cu
arcul (y,x).
Void citire_graf()
{int i, j, k, x, y;
Cout<<Nr. Arce:;cin>>m;
Cout<<nr.varfuri:;cin>>n;
{iniializeaz cu 0 toata matricea de adiacenta}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
a[i,j]=0;
13

{citete m perechi (x,y) reprezentnd arcele grafului}


for(k=1;k<=n;k++)
{
Cout<<Muchia <<k<<: ;
cin>>x;cin>>y;
while ((x>=1) || x(<=n)|| (y>=1) || (y<=n) || (x<>y))
{pentru fiecare pereche, marcheaz arcul in matricea
de adiacenta}
a[x][y]=1;
}
}

Aplicaie:
d)Determinarea gradului exterior i a gradului interior
ale unui nod oarecare x
Scriem

funcie

{d_plus(x:integer):integer;}

care

returneaz, gradul exterior al nodului x (notat d*(x)).


Gradul exterior al unui nod x este numrul arcelor care
ies din nodul x, adic numrul arcelor de forma (x,j), cu
j {1, 2, ... , n}. Lum ca exemplu graful cu n=4 noduri
de mai jos, mpreun cu matricea sa de adiacen:

A=

14
4

Analizm gradul exterior al nodului 2. Arcele care ies


din nodul 2 sunt: (2,1), (2,3), (2,4) (nu i (4,2)). Urmare
a existenei acestor arce, n matricea de adiacen vom
avea a[2,1] = a[2,3] = a[2,4] = 1. Unde se gsesc n
matricea

de

adiacen

toate

valorile

de

corespunztoare arcelor ce ies din nodul 2? Pe linia 2!


Pe caz general, valorile de 1 de pe linia x n matricea de
adiacen, reprezint arcele care ies din nodul x. Deci
gradul exterior al nodului x, adic numrul arcelor care
ies din nodul x este egal cu numrul valorilor de 1 de pe
linia x a matricei.
Aadar algoritmul implementat n funcia d_plus este
foarte simplu: Iniializm cu 0 o variabil nr. n care
numrm valorile de 1 de pe linia x a matricei. ntr-un
ciclu, parcurgem coloanele j=1, 2, ..., n ale liniei x.
Pentru fiecare valoare a lui j, testm elementul a[x,j] de
pe linia x i coloana j. Dac aceasta are valoarea 1,
atunci incrementm nr. n final funcia va returna ultima
valoare a variabilei nr.

15

int d_plus(int x);


{returneaz gradul exterior d* pentru un nod x; acesta
este numrul valorilor de 1 de pe linia x a matricei de
adiacenta}
{int nr,j;
Nr=0;
if (a[x,j] = =1) nr=nr + 1;
d_plus=nr;
}

Observaie:
Destul

de

asemntor

este

algoritmul

pentru

determinarea gradului interior al nodului x (d- (x) ).


Acesta reprezint numrul arcelor care intr n nodul x,
adic numrul arcelor de forma (i,x), cu i {1, 2, ..., n}.
S vedem unde se regsesc n matricea de adiacen
arcele care intr n nodul x, lund ca exemplu x=4
pentru graful anterior. Arcele care intr n nodul 4 sunt
(3,4) i (2,4). Rezult c n matrice avem a[3,4] = a[2,4]
= 1. Am reperat astfel valorile de 1 de pe coloana 4 a
matricei

de

adiacen.

acest

moment

putem

concluziona c gradul interior al unui nod oarecare x


reprezint numrul valorilor de 1 de pe coloana x a
matricei. Se poate scrie o funcie asemntoare cu cea

16

de mai sus, care s returneze cte valori de 1 se gsesc


pe coloana x.
function d_minus(x: integer): integer;
{returneaz gradul interior d- pentru un nod x; acesta
este numrul valorilor de 1 de pe coloana x a matricei
de adiacenta}
{Int nr, i;
nr=0;
Nr=0;
for(i=1;i<=n;i++)
if (a[x,j] = =1) nr=nr- 1;
d_plus=nr;
}

7. Matricea vrfuri arce


Este o matrice b cu n linii i m coloane, n care fiecare
element b[i,j] este:
1, dac nodul i este o extremitate iniial a arcului u j;
-1, dac nodul i este o extremitate final a arcului u j;
0, dac nodul i nu este o extremitate a arcului uj.

Exemplu:
Pentru graful de mai jos cu n=4 noduri i m=5 arce,
matricea vrfuri arce este:

-1

-1

-1

17

-1

-1

2
u1

u2

1
u4

u3
4

u5
Figura 6

Pentru a exemplifica construcia matricei, vom deduce


elementele liniei 3:
a[3,1]= 0 pentru c nodul 3 nu este o extremitate a
arcului u1. Analog, a[3,3]= 0 deoarece nodul 3 nu
este extremitate a arcului u3.
a[3,5]= -1 pentru c nodul 3 este o extremitate
final a arcului u5.
a[3,2]= 1 i a[3,4]= 1 ntruct nodul 3 este o
extremitate iniial a arcului u2 respectiv u4.

Observaii:
Pe fiecare coloan j (aferent arcului uj), avem exact
dou elemente nenule: un 1 (linia i pe care se afl
reprezint extremitatea iniial a arcului uj) i un -1
(linia i pe care se afl reprezint extremitatea final a
arcului uj)
Numrul valorilor de 1 de pe linia i, reprezint gradul
exterior

al

nodului

(numrul

arcelor

ce

au

ca

extremitate iniial pe i), iar numrul valorilor de -1 de

18

pe linia i reprezint gradul interior al nodului i (numrul


arcelor care au ca extremitate final pe i).

8. Listele vecinilor
Pentru fiecare nod x se construiesc dou liste ale
vecinilor si:
L*(x) lista vecinilor succesori; conine nodurile ce sunt
extremiti finale ale arcelor care ies din nodul x.
L-(x) lista vecinilor predecesori; conine nodurile ce
sunt extremiti iniiale ale arcelor care intr n nodul x.

Exemplu:
n graful din figura 6 de mai sus, pentru nodul x=4
avem:
arcele care ies din nodul 4 sunt (4,2) i (4,3). n
consecin,

lista

vecinilor

succesori

L*(4)

conine

nodurile 2 i 3;
n nodul 4 intr un singur arc, i anume (3,4), motiv
pentru care lista vecinilor predecesori L-(4) conine
doar nodul 3.
Prezentm

continuare

aceste

liste

ale

vecinilor

pentru graful din figura 6.


Nodul x
1
2
3
4

L*(x)
2
vid
2,4
2,3

L-(x)
vid
1,3,4
4
3

Reprezentarea grafului ca un vector de muchii


19

9.

Fiecare arc al grafului poate fi privit ca o nregistrare cu


dou componente, n spe cele dou noduri care
constituie extremitile arcului:
nod_in -> nodul din care iese arcul (nodul de
nceput al arcului);
nod_sf -> nodul n care intr arcul (nodul de
sfrit al arcului);

Putem defini tipul de date ARC, astfel:


Graful n ansamblul su, este o mulime de arce, adic o
mulime de elemente de tipul ARC. n consecin,
definim graful ca un vector de arce, adic un vector
de elemente de tipul ARC:
Numrul real de elemente este numrul de arce m.
Astfel, elementele efectiv folosite ale vectorului vor fi
v[1], v[2],..., v[m]. Fiecare element {1, 2, ..., m}) este
de tipul ARC i reprezint unv[i] (cu i arc al grafului,
avnd dou componente:
v[i].nod_in i v[i].nod_sf -> nodurile extremiti ale
arcului.

10. Nodurile izolate ntr-un graf orientat


Se citesc de la tastatur m perechi de numere ntregi
(x,y)

reprezentnd

extremitile

arcelor

unui

graf

orientat cu n noduri i m arce. S se stabileasc dac n


graful astfel definit exist noduri izolate (prin care s
nu treac nici un arc).
ntreaga

rezolvare

este

cuprins

{noduri_izolate;} fr parametri.
20

procedura

Mai nti citim numrul de noduri n i numrul de arce


m. Definim doi vectori:
dp va conine gradele exterioare (d *) ale tuturor
nodurilor;
dm va conine gradele interioare (d-) ale tuturor
nodurilor.
Astfel, dp[i] i dm[i] vor fi gradul exterior respectiv
gradul interior al nodului i, pentru i=1, 2, ..., n.
Iniializm cu 0 toate gradele exterioare i interioare
ale tuturor nodurilor: ntr-un ciclu cu i de la 1 la n,
facem atribuirile dp[i]:=0 i dm[i]:=0
Pentru a citi cele m arce, parcurgem un ciclu k de la 1 la
m, i la fiecare pas:
citim o pereche de numere ntregi (x,y), cu validarea
valorilor introduse: repet (reia) citirea lui x i y, pn
cnd ambele valori sunt >= 1 i >= n. Fiecare pereche
va reprezenta care iese din nodul x i intr n nodul y.
ntruct arcul (x,y) iese din nodul x i intr n nodul y,
rezult c:
gradul exterior al nodului x (numrul arcelor care ies
din nodul x) va crete cu 1;
gradul interior al nodului y (numrul arcelor care intr
n nodul y) va crete cu 1.
Deci se fac atribuirile dp[x]= dp[x]+1 i dm[y]= dm[y]
+1.
Aadar la citirea fiecrui arc am actualizat gradele
nodurilor extremiti ale sale. Astfel, dup ncheierea
citirii vectorii dp i dm vor conine gradele exterioare
respectiv interioare ale tuturor nodurilor.
21

Un nod x se numete izolat dac prin el nu trece nici un


arc. Altfel spus, nu iese nici un arc din el i nu intr nici
un arc n el, adic dp[x]=dm[x]=0. n continuare, vom
numra nodurile izolate n variabila nr, pe care o
iniializm cu 0. Parcurgem n paralel cei doi vectori
ai gradelor dp i dm, ntr-un ciclu cu i=1, 2, 3, ..., n. La
fiecare pas, testm dac nodul i este izolat, adic dac
dp[i]=0 i dm[i]=0; n caz afirmativ afim respectivul
nod i i incrementm numrul nr al nodurilor izolate.

nr=0;
for(i=1;i<=n;i++)
if(dp[i]=0) || (dp[i]=0) then
{
Cout<<i<< ;
nr=nr+1;
}
Dup

ncheierea

acestei

parcurgeri,

dac

numrul

vrfurilor izolate este diferit de 0 atunci l afim, iar n


caz contrar tiprim un mesaj din care s rezulte c
graful nu are noduri izolate.

22

Int Vect[20],n,m,a[20][20];
Int dp,dm;
Void noduri_izolate()
{int i,j,k,x,y,nr;
Cout<<Nr.arce : ; cin>>m;
Cout<<Nr.noduri : ; cin>>n;
{iniializeaz cu 0 vectorii gradelor dp i dm}
for(i=1;i<=n;i++)
{
dp[i]=0; dm[i]=0;
}
{citete m perechi (x,y) reprezentnd arcele grafului}
for(k=1;k<=m;k++)

23

{Cout<<Arcul<<k<<: ;
do
cin>>x;cin>>y;
while (x>=1) || x(<=n)|| (y>=1) || (y<=n) || (x<>y);
{pentru fiecare arc (x,y), incrementeaz gradul exterior
al lui x i gradul interior al lui y}
dp[x]=dp[x]+1; dm[y]=dm[y]+1;}
Cout<<endl;nr=0; {nr=numrul nodurilor izolate}
for(i=1;i<=n;i++)
{dac ambele grade ale lui i sunt 0,am gsit un vrf
izolat, pe care-l afim i incrementm nr}
if (dp[i]=0) || (dm[i]=0) then
{Cout<<i<< ; nr=nr+1;}
Cout<<endl;
if (nr!=0) cout<<Graful are <<nr<< noduri izolate;
else cout<<Graful nu are noduri izolate;}
{noduri_izolate;}

11. Celebritate
Se d un grup format din n persoane, care se cunosc
sau nu ntre ele. De la tastatur se introduc m perechi
de numere ntregi (x,y) cu semnificaia persoana x
cunoate pe persoana y. relaia de cunotin nu este
neaprat reciproc. Numim celebritate, o persoan care
este cunoscut de ctre toate celelalte persoane din
grup, dar ea nu cunoate pe nici un alt membru al
grupului. S se determine dac din grup exist o astfel
de celebritate.

24

12. Interpretarea datelor


Problema poate fi modelat ntr-un graf orientat, n
care nodurile sunt persoanele 1,2,3...n, iar arcele sunt
relaiile de cunotin ntre aceste persoane. O relaie
de cunotin este de forma (x,y) cu semnificaia
persoana x o cunoate pe persoana y. De exemplu,
dac grupul are n=4 persoane, iar cele m=5 relaii de
cunotin sunt (1,3), (2,3), (4,3), (1,2), (1,4), atunci
graful i matricea sa de adiacen arat astfel:
3
0

0
A
0

0
0
0

1
0
1

0
0

analizm

persoana

reprezentat prin nodul

3:

exist relaiile de cunotin (1,3), (2,3) i (4,3), adic


persoana 3 este cunoscut de ctre 1,2 i 4.
Mai exact, persoana 3 este cunoscut de ctre toate
celelalte persoane din grup;
nu exist nici o relaie de cunotin de forma (3,p). Cu
alte cuvinte, persoana 3 nu cunoate pe nimeni.
n

concluzie,

celebritate.

persoana
n

graf,

este

existena

ceea

ce

numim

celebritii

se

interpreteaz astfel:
n nodul 3 intr arce ieite din toate celelalte noduri;
din nodul 3 nu iese nici un arc.

25

Rezolvare
n procedura citire_graf se citesc de la tastatur m
perechi de numere ntregi de forma (x,y) reprezentnd
extremitile celor m arce ale grafului, i se constituie
matricea de adiacen a, cu n linii * n coloane.
Algoritmul de cutare a celebritii cuprins n procedura
celebritate.
Pentru nceput, vom cuta o persoan pe care o vom
numi n continuare candidat la celebritate. Memorm
acest candidat n variabila candid. Presupunem c
iniial

candidatul

este

persoana

(candid:=1).

Cercetm celelalte persoane, ntr-un ciclu cu i de la 2


la n. Pentru fiecare persoan i, trebuie s facem o
testare. n cazul n care candidatul actual candid o
cunoate i (a[candid,i] este 1) candid nu mai poate fi
celebritate (celebritate nu trebuie s cunoasc nici o
alt persoan din grup !). n aceast situaie, noul
candidat la celebritate devine i (candid:=1).
La finele parcurgerii de mai sus, n variabila candid vom
avea aadar un candidat la celebritate. Mai rmne s
vedem dac acest candidat este cunoscut de ctre
celelalte persoane.
n exemplul de mai sus, urmare a faptului c persoana
3 este celebritate, avem relaiile (1,3), (2,3) i (4,3),
adic a[1,3]=a[2,3]=a[4,3]=0. n consecin, pe coloana
3 avem n-1 valori de 1. Pe caz general, trebuie s
numrm valorile de 1 de pe coloana candid n matricea
26

de adiacen, n adiacen, iar dac gsim n-1 valori,


atunci persoana candid este ntr-adevr celebritate.

Int n, m, a[20] [20] ;


void citire_graf()
{int i, j, k, x, y;
Cout<<Nr.arce : ; cin>>m;
Cout<<Nr.noduri : ; cin>>n;
{iniializeaz cu 0 toata matricea de adiacenta}
for(i=1;i<=n;i++)
for(i=1;i<=n;i++)
a[i][j]=0;
{citete m perechi (x,y) reprezentnd arcele grafului}
for(i=1;i<=n;i++)
{Cout<<Arcul <<k<<:);

27

do

13.

cin>>x;cin>>y;
while (x>=1) || x(<=n)|| (y>=1) || (y<=n) || (x<>y);

Drumuri si

{pentru

circuite

fiecare

pereche

marcheaz

arcul

matricea de adiacenta}

in

grafuri

a[x][y]=1;}}

orientate
Se

lan

in

intr-un

graf

orientat,

mulime

numete
de

arce

L={u1,u2,...,uk}, cu proprietatea ca oricare doua arce


vecine in mulime au o extremitate comuna.

28

Un lan este de fapt un traseu care unete prin arce


doua noduri numite extremitile lanului, fr a tine
cont de orientarea arcelor componente.
Int celebritate;
Int i, j, candid, nr ;
{candid:=1; {candid va reprezenta candidatul la
celebritate, care iniial este persoana 1}
for(i=2;i<=n;i++)
{daca candidatul l cunoate pe i, el nu mai poate fi
celebritate noul candidat devine i}
if (a[candid][ i]==1) candid=i;
nr=0; {numaram in nr cate persoane l cunosc pe
candidatul candid}
for(i=1;i<=n;i++)
if (a[i][candid]=1) nr=nr+1;
{verificam daca intr-adevr candid este celebritate}
if (nr=n-1) cout<<Persoana <<candid<< este
celebritate;
else
cout<<Nu exista celebritate in grup;}
{citire_graf; celebritate;}
Se numete drum n graful G, un ir de noduri D={z 1, z2,
z3, , zk}, unde z1, z2, z3, , zk aparin lui x, cu
proprietatea c oricare dou noduri consecutive sunt
adiacente, adic exist arcele [z1, z2], [z2, z3], , [zk-1,zk]
aparin lui U.
Practic, un drum poate fi privit ca un traseu n care
toate arcele au aceeai orientare, dat de sensul de
deplasare de la z1 la zk. Dac nodurile z1, z2, z3, , zk
29

sunt distincte dou cte dou, drumul se numete


elementar. n caz contrar, drumul este ne-elementar.
Asemenea uni lan ntr-un graf neorientat, un drum ntrun graf orientat este de fapt un traseu pe care l-am
parcurge ntre dou noduri deplasndu-ne de-a lungul
unor arce i trecnd prin nite noduri intermediare.
Deosebirea unui drum fa de un lan const n faptul
c de-a lungul unui arc ne putem deplasa numai n
sensul dat de orientarea arcului.
Se numete circuit ntr-un graf, un lan L={z1, z2, z3, ,
zk} cu proprietatea c z1=zk i arcele [z1, z2], [z2, z3], ,
[zk-1,zk] sunt distincte dou cte dou.
Dac ntr-un circuit, toate nodurile cu excepia primului
i ultimului sunt distincte dou cte dou, atunci
circuitul se numete elementar. n caz contrar, el este
ne-elementar.
u2

u1
u4

u3
u5

5
u7

u6

6
Figura 8

14. Matricea drumurilor


Este o matrice d cu n linii i n coloane, n care fiecare
element d[i,j] este :
1, dac exist drum de la nodul i la nodul j n graf;
30

0, n caz contrar.

15. Algoritmul Roy-Warshall de determinare a


matricei drumurilor
Matricea drumurilor se obine aplicnd matricei de
adiacen transformri succesive. Vom spune c exist
drum de la nodul i la nodul j, dac gsim un nod k
(diferit de i, j) cu proprietatea c exist drum de la i la k
i drum de la j la k. Astfel:
un element a[i, j] care este 0, devine 1, dac exist un
nod k astfel nct a[i, k]=1 i a[k, j]=1.
for(i=1;i<=n;i++)
for(i=1;i<=n;i++) {ik}
for(j=1;j<=n;j++){jk}
if (a[i][ j]=0) || (i<>k) || (j<>k)

a[i]

[j]=a[i][k]*a[k][ j];

Pentru a gsi arcele nodului k, trebuie parcurse pe rnd


n varianta k toate nodurile 1, 2, , n.
Atribuirea a[i][ j]=a[i][k]*a[k][ j] este o scriere elegant
a regulii de mai sus:
n cazul n care unul din elementele a[i][k], a[k][ j] este
0, a[i][ j] va rmne 0;
dac a[i, k]=1 i a [k, j]=1, atunci a[i, j] devine 1.

31

Problema rezolvata : Un CD valoros


ntr-un grup sunt n elevi, biei i fete, pe care-i
numerotm 1, 2, , n. Fiecare elev cunoate o parte
dintre ceilali elevi. Relaia de cunotin nu este
neaprat reciproc (dac x l cunoate pe y, asta nu
nseamn c i y trebuie s l cunoasc pe x).
Unul dintre elevi are un CD foarte valoros, cu multe
jocuri demonstrative, pe care toi membri grupului vor
s-l aib fie i pentru scurt timp, pentru a i-l copia pe
calculatorul propriu.
CD-ul circul printre membrii grupului n felul urmtor:
fiecare elev dup ce l-a primit de la altcineva l d mai
departe, dar numai unui elev pe care l cunoate, pentru
c nu dorete s ajung n mna unor persoane n care
nu poate avea ncredere. Determinai o modalitate
(dac exist) prin care CD-ul s circule exact o singur
dat pe la fiecare elev, transmiterea lui fcndu-se
numai ctre o cunotin, iar n final CD-ul s ajung din
nou la proprietarul su.
Interpretarea datelor
Relaiile

de

cunotin

din

cadrul

grupului

pot

fi

reinute ntr-o matrice a cu n linii i n coloane, n fiecare


element a[i, j] este: 1 dac elevul i l cunoate pe elevul
j, respectiv 0 n caz contrar.
Cu datele problemei putem construi un graf n care
nodurile sunt elevii 1, 2, 3,, n, iar arcele sunt relaiile
de cunotin din grup. Astfel, va exista arc de la nodul
x la nodul y dac elevul x n cunoate pe elevul y.
32

ntruct n enun se precizeaz c relaiile de cunotin


nu sunt neaprat reciproce (x cunoate pe y nu
implic y cunoate pe x), rezult c avem de-a face cu
un graf orientat. Matricea a

definit mai nainte este

tocmai matricea de adiacen a grafului.


"Traseul" pe care l parcurge CD-ul pleac dintr-un nod
(proprietarul su), trecnd prin fiecare nod (pe la
fiecare elev) o singur dat. Transmiterea se face numai
ctre o cunotin. Astfel, de la elevul x va ajunge la
elevul y numai dac exist arc (cunotin) de la x la y.
n final, traseul se ncheie n nodul de unde a plecat
(CD-ul se ntoarce la proprietarul iniial). Un traseu care
respect condiiile de mai sus nu este altceva dect un
circuit elementar care trece prin toate nodurile grafului:
drum deoarece poate trece de la un nod la altul numai
printr-un arc, elementar deoarece nu trece de dou ori
prin acelai nod, i n sfrit circuit pentru c revine n
nodul de plecare.

Rezolvare :
Folosim metoda backtracking. Fiecare astfel de circuit
elementar care trece prin toate nodurile grafului, va fi o
soluie

memorat

vectorul

stiv

st.

Aadar

elementele vectorului st sunt noduri ale grafului.


O soluie (st[1], st[2], , st[p] ) este final dac
conine n nivele, adic p=n (au fost pui pe stiv
toi cei n elevi, adic toate cele n noduri)
33

st[n]=x (pentru a fi ciclu trebui s revin n nodul


de plecare, adic elevul de pe ultimul nivel, st[n],
trebuie s fie proprietarul memorat iniial n x).
Procedura

{citire_matrice;}

citete

matricea

de

adiacen (relaiile de cunotin). n dou cicluri for, cu


i, j=1, 2, , n, se citesc toate elementele a[i, j]. Aceast
procedur a fost prezentat ca aplicaie n lecia
Reprezentarea grafurilor orientate
Procedura {iniializri;} realizeaz iniializarea stivei i
a proprietarului CD-ului.
ntr-un ciclu for, se iniializeaz cu 0 ntreg vectorulstiv;
se citete numrul de ordine al proprietarului CD-ului n
variabila x (nodul de plecare).
Procedura {tipar(p:integer):} afieaz o configuraie
(st[1], st[2], , st[p]) a vectorului-stiv.
Funcia

{valid(p:integer):boolean;}

verific

pentru

fiecare nivel p dac st[p]I a generat o soluie (st[1],


st[2], , st[p]) valid.
Testarea

se

face

prin

intermediul

unei

variabile

booleene ok, iniializeaz cu TRUE. n primul rnd, din


nodul st[p-1] se poate ajunge n nodul st[p] numai
printr-un arc (orice drum/circuit trece prin arce). Aadar
nodul st[p] este valid numai dac exist arc de la st[p1] la st[p], adic a[st[p-1], st[p]]=1 (aceast condiie
provine din faptul c fiecare elev va transmite CD-ul
numai prin cunotin, ia relaia de cunotin este
marcat n graf printr-un arc). n caz contrar ok devine
FALSE.
34

Dac ok a rmas TRUE, urmeaz testarea celei de-a


doua condiii. Am spus c soluia este final dac p=n,
iar pe ultimul nivel trebuie s se gseasc nodul x. Dar
pe ultimul nivel anterior lui n nu putem avea nodul x
(CD-ul revine la proprietar, dar numai dup ce a trecut
pe la ceilali elevi, pe la fiecare o singur dat).
if (ok)
if ((p<n) &(st[p]==x))
ok=0 (FALSE)

Dac ok a rmas n continuare TRUE, mai avem i o a


treia condiie. Nodul st[p] s nu se mai gseasc pe
stiv (urmare a faptului c CD-ul trebuie s treac pe la
fiecare elev o singur dat).
Parcurgem

ntr-un

ciclu

nivelele

i=1,

2,

p-1

anterioare lui p. Dac gsim un st[i] egal cu st[p],


nseamn c st[p] se mai gsesc pe un nivel anterior,
deci ok devine i n cazul acesta FALSE.
Procedura recursiv {bktr(p:integer);} trateaz un
nivel oarecare p al stivei. Prin variabila val vor trece pe
rnd, ntr-un ciclu, toate valorile care teoretic ar putea
fi puse pe nivelul p. Pentru fiecare dintre aceste valori:
- dac respectiva valoare a generat o soluie valid
(dac funcia valid(p) a returnat TRUE), atunci:
- dac soluia respectiv e i final o tiprim (apelnd
procedura tipar (p)); n caz contrar trecem la nivelul

35

urmtor (pentru a completa soluia cu un nou nivel),


prin auto-apelul bktr(p+1).
n programul principal, apelm procedurile iniializri i
citire_matrice,

apoi

declanm

lanul

recursiv

apelul bktr(1) (plecm de la nivelul 1 al stivei).

int n,xr;
int st[20],a [20][20];
procedure citire_matrice;
{citeste matricea de adiacenta a de la tastatura}
{var I,j:integer;
Cout<< numarul de noduri: ; cin>>n;
for(i=1;i<=n;i++)
for(i=1;i<=n;i++)
{write ([, i, ,, j, ]=); cin>>(a[i, j]);}}
void initializari()
{initializeaza stiva si citeste datele problemei}
Int i;
{cout<<Cine este proprietarul: ; cin>>x;
for(i=1;i<=25;i++)
st();}
Int tipar (int p);
{tipareste o solutie memorata in vectorul st}
{Int k;
Cout<<x<<;
for(i=1;i<=n;i++)
do cout<<st[k] ;
cout<<endl;
36

prin

function valid(int p)
{testeaza daca valoarea pusa pe nivelul p a generat o
solutie valida, returnand TRUE sau FALSE}
Int nr, i, ok;
{{CD-ul poate circula numai intre elevii care se cunosc,
deci elevul st[p-1] trebuie sa il cunoasca pe st[p] pentru
a-i putea da CD-ul mai departe}
ok=1;(TRUE)
if (a[st[p-1], st[p]]==0) then ok=0;
if (ok)
{proprietarul x nu se poate gasi pe un nivel anterior
ultimului}
if (p<n) and (st[p]==x) then ok=0;
if (ok)
{elevul st[p] nu trebuie sa se mai gaseasca pe nivelele
anterioare}
for (i=1;i<=p-1;i++)
if (st[p]==st[i]) ok=0;
valid=ok;
end;
void bktr (int p)
{implementeaza algoritmul de backtracking recursiv}
Int val;
{{in variabila val trec pe rand toate valorile care ar
putea fi incercate pe nivelul p al stivei}
for(i=1;i<=n;i++)
{st[p]=val; {pune o noua valoare pe nivelul p}
if valid(p) {daca solutia obtinuta e valida}

37

{o solutie e finala daca CD-ul a trecut pe la n elevi


(p=n) si ultimul e proprietarul (st[p]=x)}
if ((p=n) ||(st[n]==x))

tipar (p) {daca e si finala,

tipareste solutia}
else bktr (p+1); {trece la nivelul urmator in stiva,
pentru a completa solutia}}}
{citire_matrice; bktr(1); {plecam de la nivelul 1 pe
stiva}}

Informatica - profil matematica-informatica


Lucrarea studiaza limbajul C++ si se adreseaza elevilor din clasele IX-X care au studiat
limbajele C si Pascal
Cornelia Ivasc, Mona Carmen-Pruna, Luminita-Mihaela Condurache, Doina LogofatuHrinciuc Editura Petrion
Informatica - Manual pentru clasa a XI-a
Autor : Mariana Milosescu
Limbajul C/C++ - teorie si aplicatii (clasa a XI-a)
Autor : Cristian Udrea

38

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