Sunteți pe pagina 1din 25

Grafuri orientate noiuni de baz

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 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 cuvinte muchiile sunt difereniate prin ordinea de scriere a simbolurilor. Arcul (x,y) nu este tot una cu arcul (y,x). Exemplu:
3 U6 U7 4 U3 U5 U4 U2 2 U1 1

Figura1

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) 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 mulimea nodurilor ce constituie extremiti iniiale

ale arcelor care pleac din nodul x. Pe scurt, mulimea succesorilor lui x;
( x ) = { y X ( y, x ) U }

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 U

. Altfel spus, un graf parial G1 al lui G, este chiar G, sau se obine din G Fie graful G = (X,U). Un graf parial al lui G, este un graf G1= (Y,T),

pstrnd toate vrfurile i suprimnd nite muchii. 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.
1 u1 u4 4 u7 u6 3 u2 u3 u5 5 4 u7 u6 u4 3 5 4 u7 u6 2 1 u2 u3 2

u4

u5 5

6 Figura 2

6 Figura 3

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

1 0

2 0 0 0 1

3 0 1 0 0

4 0 1 1 0 1 2 3 4

A=

1 0 0

1 4

Continum cu cteva aplicaii. 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;
Figura 5

{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, 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]. 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: 1 0 A= 1 0 0 2 0 0 0 1 3 0 1 0 0 4 0 1 1 0 1 2 3 4

1 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 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 0 0 0 -1 1 0 0 -1 0 1 0 0 1 -1 0 0 -1 1

2 u1 u3 4 u5 Figura 6

u2 3

1 u4

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 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: L*(x) 2 vid 2,4 2,3 L-(x) vid 1,3,4 4 3

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
0 0 A = 0 0 1 0 0 0 1 1 0 1 1 0 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.
1 u1 u4 4 u7 u6 6 Figura 8 3 u2 u3 u5 5 2

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[p1], 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 printrun 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.