Sunteți pe pagina 1din 28

GRAFURI ORIENTATE

Scurt istoric:

Graful este la origine un concept matematic. Teoria grafurilor are o


vechime mult mai mare comparativ cu informatica. n informatic graful este
privit ca o structur de date. O particularitate a grafurilor n informatic este
faptul c de fiecare dat sunt considerate grafuri finite (cu numr finit de
noduri). Informatica a preluat noiunile teoriei grafurilor imaginnd o
multitudine de situaii concrete rezolvabile cu algoritmi ce prelucreaz structuri
asimilate grafurilor.
Euler Leonhard
Nscut la Basel (Elvetia) n 1707, s-a remarcat ca fizician i
matematician. Se apreciaz ca a fost figura predominant a sec. XVIII n
domeniul matematicii Euler este printre cei mai prolifici autori n specialitatea
sa, publicnd pe parcursul vieii peste 70 volume. Moare n anul 1783 la St.
Petersburg, Rusia.
A avut contribuii decisive n demonstrarea unor teoreme matematice, n
teoria numerelor, a funciilor trigonometrice i desigur, a grafurilor.

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 n 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 o mulime format din perechi ordonate de elemente ale lui X, numit
mulimea arcelor (muchiilor)
observaii:
Prin noiunea de perechi ordonate nu trebuie
U1

s nelegem c o muchie este mai mare dect alta,

ci pur i simplu c facem deosebire ntre o muchie


de forma (x,z) i o alta de forma (y,x). Cu alte

U2
2

cuvinte muchiile sunt difereniate prin ordinea de

U3
U5

scriere a simbolurilor.
Arcul (x,y) nu este tot una cu arcul (y,x).
Exemplu:

U4
3
U6
U7

Pentru graful G=(X,U) din figura 1. avem:


X={1, 2, 3, 4} i U={u1, u2, u3, u4, u5, u6, u7,}=

Figura1

{(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)
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.
Graful unui vrf. 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)}
Graf parial i subgraf
Fie graful G = (X,U). Un graf parial al lui G, este un graf G1= (X,V),
cu V

. 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 X = {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 mulimii
nodurilor rmase.
u2

u1
u4

u2

u3
u4

u5

5
u7

u3

u6

5
u7

6
Figura 2

u4

u5

u6

6
Figura 3

5
u7

u6

6
Figura 4

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.
Matricea de adiacen
Are aceeai semnificaie ca n 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=

1
4

Continum
aplicaii.

cu cteva
Figura 5

Aplicaie:
Citirea de la tastatur i afiarea matricei de adiacen
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 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.
Procedure citire_matrice;
{citete matricea de adiacen a de la tastatur}

var i,j: integer;


begin
writeln('Nr. Noduri: '); readln(n);
for i:=1 to n do
for j:=1 to n do
begin
write('[',i,',',j,']=');
readln(a[i,j]);
end;
end;
Procedure afiare_matrice;
{afieaz matricea de adiacen a}
var i,j: integer;
begin
for i:=1 to n do
begin
for j:=1 to n do
write(a[i,j],' ');
writeln();
end;
end;
Aplicaie:
Citirea matricei de adiacen dintr-un fiier text
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 c
fiierul conine pe primul rnd valoarea lui n, apoi pe fiecare din urmtoarele
n rnduri elementele unei linii a matricei separate de spaii.
Procedure cit_matr_fis;
{citete numrul de noduri si matricea de adiacenta a din fiierul text
cu descriptorul f}
var i,j: integer; nume_fis: string;
begin
write('Dai numele fiierului '); readln(nume_fis);

assign(f,nume_fis); reset(f);
readln(f,n);
for i:=1 to n do
begin
for j:=1 to n do read(f,a[i,j]);
readln(f);
end;
close(f);
end;
Aplicaie:
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 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, ntrun 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].
repeat
readln(x,y);
until (x>=1) and x(<=n) and (y>=1) and (y<=n) and (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).
Algoritmul prezentat a fost inclus n procedura citire_graf.
Procedure citire_graf;
var i, j, k, x, y: integer;
begin

write('Nr. Arce:'); readln(m);


write('Nr. Vrfuri'); readln(n);
{iniializeaz cu 0 toata matricea de adiacenta}
for i:=1 to n do
for j:=1 to n do
a[i,j]:=0;
{citete m perechi (x,y) reprezentnd arcele grafului}
for k:=1 to m do
begin
write('Muchia ',k,': ');
repeat
readln(x,y);
until (x>=1) and x(<=n) and (y>=1) and (y<=n) and (x<>y);
{pentru fiecare pereche, marcheaz arcul in matricea de adiacenta}
a[x,y]:=1;
end;
end;
Aplicaie:
Determinarea gradului exterior i a gradului interior ale unui nod
oarecare x
Scriem o 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=

Analizm

nodului 2. Arcele care

gradul exterior al
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 1 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.
Function d_plus(x:integer):integer;
{returneaz gradul exterior d* pentru un nod x; acesta este numrul
valorilor de 1 de pe linia x a matricei de adiacenta}
var nr.,j: integer;
begin

nr.:=0;
for j:=1 to n do
if a[x,j] = 1 then nr:=nr + 1;
d_plus:=nr;
end;
Observaie:
Destul de asemntor este i 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. n 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 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}
var nr, i: integer;
begin
nr:=0;
for i:=1 to n do
if a[i,x]=1 then nr:=nr+1;
d_minus:=nr;
end;
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 uj;


- -1, dac nodul i este o extremitate final a arcului uj;
- 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

-1

-1

-1

u2

u1

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 i (numrul arcelor ce au ca extremitate iniial pe i), iar numrul
valorilor de -1 de pe linia i reprezint gradul interior al nodului i (numrul
arcelor care au ca extremitate final pe i).
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 n continuare aceste liste ale vecinilor pentru graful din
figura 6.
Nodul x
1
2
3
4
Matricea drumurilor

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

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

Aceast matrice va fi reprezentat n cadrul capitolului Drumuri i


circuite n grafuri orientate.
Reprezentarea grafului ca un vector de muchii
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:
type ARC=record
nod_in, nod_sf: integer;
end;
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:
var v: array [1..25] of 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.
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 n procedura {noduri_izolate;} fr


parametri.
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.
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 to n do
if(dp[i]=0) and (dp[i]=0) then
begin
write(i,' ');
nr:=nr+1;
end;
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.
Program XI_7;
type vect =array[1..20] of integer;
var n,m:integer;
a:array[1..20,1..20] of integer;
dp,dm:vect;
procedure noduri_izolate;
var i,j,k,x,y,nr:integer;
begin
write('Nr.arce : '); readln(m);
write('Nr.noduri: '); readln(n);
{iniializeaz cu 0 vectorii gradelor dp i dm}
for i:=1 to n do
begin
dp[i]:=0; dm[i]:=0;
end;
{citete m perechi (x,y) reprezentnd arcele grafului}
for k:=1 to m do
begin
write('Arcul ',k,': ');
repeat

readln(x,y);
until (x>=1) and (x<=n) and (y>=1) and (y<=n) and (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;
end;
writeln; nr:=0; {nr=numrul nodurilor izolate}
for i:=1 to n do
{dac ambele grade ale lui i sunt 0,am gsit un vrf izolat, pe care-l
afim i incrementm nr}
if (dp[i]=0) and (dm[i]=0) then
begin
write(i,' '); nr:=nr+1;
end;
writeln;
if nr<>0 then writeln('Graful are ',nr, ' noduri izolate')
else writeln ('Graful nu are noduri izolate');
end;
begin
noduri_izolate;
end.
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.
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
1
0

1
1

0
0

0
0

0
1

0
0

S 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, persoana 3 este ceea ce numim celebritate. n graf,
existena celebritii se interpreteaz astfel:
- n nodul 3 intr arce ieite din toate celelalte noduri;
- din nodul 3 nu iese nici un arc.
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 1 (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 de adiacen, n adiacen, iar dac gsim n-1 valori, atunci
persoana candid este ntr-adevr celebritate.
Program XI_8;
var n, m: integer; a: array[1..20, 1..20] of integer;
procedure citire_graf;
var i, j, k, x, y: integer;
begin
write('Nr. arce: '); readln(m);
write('Nr. noduri: '); readln(n);
{iniializeaz cu 0 toata matricea de adiacenta}
for i:=1 to n do
for j:=1 to m do
a[i,j]:=0;
{citete m perechi (x,y) reprezentnd arcele grafului}
for k:=1 to m do
begin
write('Arcul ',k,': ');
repeat

readln(x,y);
until (x>=1) and (x<=n) and (y>=1) and (y<=n) and (x<>y);
{pentru fiecare pereche marcheaz arcul in matricea de adiacenta}
a[x,y]:=1;
end;
end;
procedure celebritate;
var i, j, candid, nr : integer;
begin
candid:=1; {candid va reprezenta candidatul la celebritate, care
iniial este persoana 1}
for i:=2 to n do
{daca candidatul l cunoate pe i, el nu mai poate fi celebritate noul
candidat devine i}
if a[candid, i]=1 then candid:=i;
nr:=0; {numaram in nr cate persoane l cunosc pe candidatul
candid}
for i:=1 to n do
if a[i, candid]=1 then nr:=nr+1;
{verificam daca intr-adevr candid este celebritate}
if nr=n-1 then writeln('Persoana ', candid,' este
celebritate')
else writeln('Nu exista celebritate in grup');
end;
begin
citire_graf; celebritate;
end.
Drumuri si circuite in grafuri orientate
Se numete lan intr-un graf orientat, o mulime de arce L={u1,u2,...,uk},
cu proprietatea ca oricare doua arce vecine in mulime au o extremitate
comuna.
Un lan este de fapt un traseu care unete prin arce doua noduri numite
extremitile lanului, fr a tine cont de orientarea arcelor componente.

Se numete drum n graful G, un ir de noduri D={z1, 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 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 ntr-un 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

1
u1
u4

2
u3
u5

5
u7

u6
6
Figura 8

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;
- 0, n caz contrar.
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. Pentru a gsi arcele nodului k, trebuie
parcurse pe rnd n varianta k toate nodurile 1, 2, , n.
for k:=1 to n do
for i:=to n do
{ik}
for j:=1 to n do {jk}
if (a[i, j]=0) and (i<>k) and (j<>k) then
a[i, j]:=a[i,k]*a[k, j];
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.

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. CDul 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. 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 n 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)
- 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 vectorul-stiv;
- 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[p-1] 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.
ok:=TRUE;
if a [ st[p], st[p-1]]=0 then
ok:=FALSE;
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 then
if (p<n) and (st[p]=x)
then
ok:=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.
if ok then
for i:=1 to p-1 do
if st[p]= st[i] then
ok:=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
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 prin apelul bktr(1) (plecm
de la nivelul 1 al stivei).
Program XI_10;
var n,x:integer;
st:array[1..20] of integer;
a:array[1..20,1..20] of integer;
procedure citire_matrice;

{citeste matricea de adiacenta a de la tastatura}


var I,j:integer;
begin
write (numarul de noduri: ); readln(n);
for i:=1 to n do
for j:=1 to n do
begin
write ([, i, ,, j, ]=); readln(a[i, j]);
end;
end;
procedure initializari;
{initializeaza stiva si citeste datele problemei}
var i:integer;
begin
write (Cine este proprietarul: ); readln(x);
for i:=1 to 25 do st[i]:=0;
end;
procedure tipar (p:integer);
{tipareste o solutie memorata in vectorul st}
var k:integer;
begin;
write (x, );
for k:=1 to p do write (st[k]:4, );
writeln;
end;
function valid (p:integer): boolean;
{testeaza daca valoarea pusa pe nivelul p a generat o solutie valida,
returnand TRUE sau FALSE}
var nr, i:integer; ok:boolean;
begin
{CD-il 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:=TRUE;
if a[st[p-1], st[p]]=0 then ok:=FALSE;
if ok then
{proprietarul x nu se poate gasi pe un nivel anterior ultimului}
if (p<n) and (st[p]=x) then ok:=FALSE;

if ok then
{elevul st[p] nu trebuie sa se mai gaseasca pe nivelele anterioare}
for i:=1 to p-1 do
if st[p]= st[i] then ok:=FALSE;
valid:=ok;
end;
procedure bktr (p:integer);
{implementeaza algoritmul de backtracking recursiv}
var val:integer;
begin
{in variabila val trec pe rand toate valorile care ar putea fi incercate pe
nivelul p al stivei}
for val:=1 to n do
begin
st[p]:=val; {pune o noua valoare pe nivelul p}
if valid(p) then {daca solutia obtinuta e valida}
{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) and (st[n]=x) then tipar (p) {daca e si finala, tipareste
solutia}
else bktr (p+1); {trece la nivelul urmator in stiva, pentru a
completa solutia}
end;
end;
begin;
initializai; citire_matrice; bktr(1); {plecam de la nivelul 1 pe stiva}
end.

BIBLIOGRAFIE: www.didactic.ro
grupa1info.blogspot.com/2010/04/teoriegrafuri-orientate_29.html
Ro.wikipedia.org/wiki/Graf

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