Sei sulla pagina 1di 89

PROF.UNIV.DR.

HORIA IOAN GEORGESCU

TEHNICI AVANSATE DE
PROGRAMARE

1
1.1.

DESPRE ALGORITMI

Diferene ntre informatic i matematic

Este de mult vreme acceptat, dar de puin vreme recunoscut i statuat n


Romnia, faptul c informatica i matematica sunt dou tiine de-sine-stttoare.
Aceasta nu nseamn ns c informatica nu folosete instrumentul
matematic! Din contr, instrumentul matematic este esenial n informatic.
Dincolo de nevoia de a demonstra diferite aseriuni (n care intervine matematica,
dar numai prin anumite capitole!), este vorba de a avea o privire de asamblu
ordonat i coerent asupra informaticii. Fr aceast viziune care s cuprind
elementele eseniale, vom avea mereu impresia c degeaba nvm astzi unele
aspecte, pentru c peste doi ani ele vor fi demodate i nefolositoare. n fapt,
anumite aspecte sunt de durat i nsuirea lor ne va ajuta s facem fa fluxului
necontenit de informaii i produse ce apar pe pia.
Vom prezenta numai dou aspecte ce deosebesc cele dou tiine:
1) n lucrul pe calculator, majoritatea proprietilor algebrice nu sunt
satisfcute.
-

elementul neutru: egalitatea a+b=a poate fi satisfcut fr ca b=0: este


situaia n care b0, dar ordinul su de mrime este mult mai mic dect al lui
a, astfel nct memorarea unui numr limitat de cifre i aducerea la acelai
exponent fac ca, la efectuarea adunrii, b s fie considerat egal cu 0.

comutativitate: s considerm urmtoarea funcie scris n Pascal ce folosete


apelul prin referin:

function f(var a:integer):integer;


begin a:=a+1; f:=a end;

Secvena de instruciuni:
a:=1; write (a+f(a))

produce la ieire valoarea 1+2=3, pe cnd secvena de instruciuni:


a:=1; write (f(a)+a))

produce la ieire valoarea 2+2=4.

1. DESPRE ALGORITMI

asociativitate: pentru simplificare (dar fr a reduce din generalitate) vom


presupune c numerele sunt memorate cu o singur cifr semnificativ i c la
nmulire se face trunchiere. Atunci rezultatul nmulirilor (0.50.7)0.9
este 0.30.9=0.2, pe cnd rezultatul nmulirilor 0.5(0.70.9) este
0.50.6=0.3.

2) Nu intereseaz n general demonstrarea teoretic a existenei unei soluii, ci


accentul este pus pe elaborarea algoritmilor.
Vom pune n vedere acest aspect prezentnd o elegant demonstraie a
urmtoarei propoziii:
Propoziie. Exist ,R\Q cu Q.
Pentru demonstraie s considerm numrul real x=aa, unde a= 2 .
Dac xQ, propoziia este demonstrat.
Dac xQ, atunci xa=a2=2Q i din nou propoziia este demonstrat.
Frumuseea acestei scurte demonstraii nu poate satisface pe un
informatician, deoarece lui i se cere n general s furnizeze un rezultat i nu s
arate existena acestuia.

1.2.

Aspecte generale care apar la rezolvarea unei probleme

Aa cum am spus, informaticianului i se cere s elaboreze un algoritm


pentru o problem dat, care s furnizeze o soluie (fie i aproximativ, cu
condiia menionrii acestui lucru).
Teoretic, paii sunt urmtorii:
1) demonstrarea faptului c este posibil elaborarea unui algoritm pentru
determinarea unei soluii;
2) elaborarea unui algoritm (caz n care pasul anterior devine inutil);
3) demonstrarea corectitudinii algoritmului;
4) determinarea timpului de executare a algoritmului;
5) demonstrarea optimalitii algoritmului (a faptului c timpul de executare este
mai mic dect timpul de executarea al oricrui alt algoritm pentru problema
studiat).
Evident, acest scenariu este idealist, dar el trebuie s stea n permanen n
atenia informaticianului.
n cele ce urmeaz, vom schia cteva lucruri legate de aspectele de mai
sus, nu neaprat n ordinea menionat.

1.3. Timpul de executare a algoritmilor

1.3.

Timpul de executare a algoritmilor

Un algoritm este elaborat nu numai pentru un set de date de intrare, ci


pentru o mulime de astfel de seturi. De aceea trebuie bine precizat mulimea
(seturilor de date) de intrare. Timpul de executare se msoar n funcie de
lungimea n a datelor de intrare.
Ideal este s determinm o formul matematic pentru T(n)=timpul de
executare pentru orice set de date de intrare de lungime n. Din pcate, acest lucru
nu este n general posibil. De aceea, n majoritatea cazurilor ne mrginim la a
evalua ordinul de mrime al timpului de executare.
Mai precis, spunem c timpul de executare este de ordinul f(n) i
exprimm acest lucru prin T(n)=O(f(n)), dac raportul ntre T(n) i f(n)
tinde la un numr real atunci cnd n tinde la .
De exemplu, dac f(n)=nk pentru un anumit numr k, spunem c
algoritmul este polinomial.
Specificm, fr a avea pretenia c dm o definiie, c un algoritm se
numete "acceptabil" dac este este polinomial. n capitolul referitor la metoda
backtracking este prezentat un mic tabel care scoate n eviden faptul c
algoritmii exponeniali necesit un timp de calcul mult prea mare chiar pentru un
n mic i indiferent de performanele calculatorului pe care lucrm.
De aceea, n continuare accentul este pus pe prezentarea unor algoritmi
polinomiali.

1.4.

Corectitudinea algoritmilor

n demonstrarea
importante:

corectitudinii

algoritmilor,

exist

dou

aspecte

Corectitudinea parial: presupunnd c algoritmul se termin (ntr-un numr


finit de pai), trebuie demonstrat c rezultatul este corect;
 Terminarea programului: trebuie demonstrat c algoritmul se ncheie n timp
finit.
Evident, condiiile de mai sus trebuie ndeplinite pentru orice set de date
de intrare admis.

Modul tipic de lucru const n introducerea n anumite locuri din program


a unor invariani, adic relaii ce sunt ndeplinite la orice trecere a programului
prin acele locuri.
Ne mrginim la a prezenta dou exemple simple.

1. DESPRE ALGORITMI

Exemplul 1. Determinarea concomitent a celui mai mare divizor comun


i a celui mai mic multiplu comun a dou numere naturale.
Fie a,bN*. Se caut:
 (a,b)=cel mai mare divizor comun al lui a i b;
 [a,b]=cel mai mic multiplu comun al lui a i b.
Algoritmul este urmtorul:
x a; y b; u a; v b;
while xy
{ xv+yu = 2ab; (x,y)=(a,b) }
if x>y then x x-y; u u+v
else y y-x; v u+v
write(x,(u+v)/2)

(*)

Demonstrarea corectitudinii se face n trei pai:


1) (*) este invariant:
La prima intrare n ciclul while, condiia este evident ndeplinit.
Mai trebuie demonstrat c dac relaiile (*) sunt ndeplinite i ciclul se
reia, ele vor fi ndeplinite i dup reluare.
Fie (x,y,u,v) valorile curente la o intrare n ciclu, iar (x',y',u',v')
valorile curente la urmtoarea intrare n ciclul while. Deci: xv+yu=2ab i
(x,y)=(a,b).
Presupunem c x>y. Atunci x'=x-y, y'=y, u'=u+v, v'=v.
x'v'+y'u'=(x-y)v+y(u+v)=xv+yu=2ab i
(x',y')=(x-y,y)=(x,y)=(a,b).
Cazul x<y se studiaz similar.
2) Corectitudinea parial:
La ieirea din ciclul while, x=(x,x)=(x,y)=(a,b). Notm
d=(a,b)=x. Conform relaiilor (*), avem d(u+v)=2d2, unde a=d i
b=d. Atunci (u+v)/2=d=ab/d=[a,b].
3) Terminarea programului:
Fie {xn}, {yn}, {un}, {vn} irul de valori succesive ale variabilelor. Toate
aceste valori sunt numere naturale pozitive. Se observ c irurile {xn} i
{yn} sunt descresctoare, iar irul {xn+yn} este strict descresctor. Aceasta
ne asigur c dup un numr finit de pai vom obine x=y.
Exemplul 2. Metoda de nmulire a ranului rus.
Fie a,bN. Se cere s se calculeze produsul ab.
ranul rus tie doar:

1.4. Corectitudinea algoritmilor

s verifice dac un numr este par sau impar;


s adune dou numere;
s afle ctul mpririi unui numr la 2;
s compare un numr cu 0.
Cu aceste cunotine, ranul rus procedeaz astfel:

x a; y b; p 0
while x>0
{ xy+p=ab }
if x impar then p p+y
x x div 2; y y+y
write(p)

(*)

S urmrim cum decurg calculele pentru x=54, y=12:


x
54
27
13
6
3
1
0

y
12
24
48
96
192
384
?

p
0
24
72
264
648

Ca i pentru exemplul precedent, demonstrarea corectitudinii se face n trei pai:


1) (*) este invariant:
La prima intrare n ciclul while, relaia este evident ndeplinit.
Mai trebuie demonstrat c dac relaia (*) este ndeplinit i ciclul se reia,
ea va fi ndeplinit i la reluare.
Fie (x,y,p) valorile curente la o intrare n ciclu, iar (x',y',p')
valorile curente la urmtoarea intrare n ciclul while. Deci: xy+p=ab.
Presupunem c x este impar. Atunci (x',y',p')=((x-1)/2,2y,p+y).
Rezult x'y'+p'=(x-1)/22y+p+y=xy+p=ab.
Presupunem c x este par. Atunci (x',y',p')=(x/2,2y,p). Rezult
x'y'+p'=xy+p=ab.
2) Corectitudinea parial:
Dac programul se termin, atunci x=0, deci p=ab.
3) Terminarea programului:
Fie {xn}, {yn} irul de valori succesive ale variabilelor corespunztoare.
Se observ c irul {xn} este strict descresctor. Aceasta ne asigur c
dup un numr finit de pai vom obine x=0.

1. DESPRE ALGORITMI

10

1.5.

Optimalitatea algoritmilor

S presupunem c pentru o anumit problem am elaborat un algoritm i


am putut calcula i timpul su de executare T(n). Este natural s ne ntrebm
dac algoritmul nostru este "cel mai bun" sau exist un alt algoritm cu timp de
executare mai mic.
Problema demonstrrii optimalitii unui algoritm este foarte dificil, n
mod deosebit datorit faptului c trebuie s considerm toi algoritmii posibili i
s artm c ei au un timp de executare superior.
Ne mrginim la a enuna dou probleme i a demonstra optimalitatea
algoritmilor propui, pentru a pune n eviden dificultile care apar.
Exemplul 3. Determinarea celui mai mic element al unui vector.
Se cere s determinm m=min(a1,a2,...,an).
Algoritmul binecunoscut este urmtorul:
m a1
for i=2,n
if ai<m then m ai
care necesit n-1 comparri ntre elementele vectorului a=(a1,a2,...,an).

Propoziia 1. Algoritmul de mai sus este optimal.


Trebuie demonstrat c orice algoritm bazat pe comparri necesit cel puin
n-1 comparri.
Demonstrarea optimalitii acestui algoritm se face uor prin inducie.
Pentru n=1 este evident c nu trebuie efectuat nici o comparare.
Presupunem c orice algoritm care rezolv problema pentru n numere
efectueaz cel puin n-1 comparri i s considerm un algoritm oarecare care
determin cel mai mic dintre n+1 numere. Considerm prima comparare efectuat
de acest algoritm; fr reducerea generalitii, putem presupune c s-au comparat
a1 cu a2 i c a1<a2. Atunci m=min(a1,a3,...,an=1). Dar pentru determinarea
acestui minim sunt necesare cel puin n-1 comparri, deci numrul total de
comparri efectuat de algoritmul considerat este cel puin egal cu n.
Exemplul 4. Determinarea minimului i maximului elementelor unui
vector.
Se

cere

determinarea
valorilor
m=min(a1,a2,...,an)
i
M=max(a1,a2,...,an).
Determinarea succesiv a valorilor m i M necesit timpul T(n)=2(n-1).

1.5. Optimalitatea algoritmilor

11

O soluie mai bun const n a considera cte dou elemente ale


vectorului, a determina pe cel mai mic i pe cel mai mare dintre ele, iar apoi n a
compara pe cel mai mic cu minimul curent i pe cel mai mare cu maximul curent:
if n impar then m a1; M a1; k 1
else if a1<a2 then m a1; M a2
else m a2; M a1
k 2
{ k = numrul de elemente analizate }
while kn-2
if ak+1<ak+2 then if ak+1<m then m ak+1
if ak+2>M then M ak+2
else if ak+2<m then m ak+2
if ak+1>M then M ak+1
k k+2

S calculm numrul de comparri efectuate:


pentru n=2k, n faza de iniializare se face o comparare, iar n continuare se
fac 3(k-1) comparri; obinem T(n)=1+3(k-1)=3k-3=3n/2-2=3n/22.
pentru n=2k+1, la iniializare nu se face nici o comparare, iar n continuare se
fac 3k comparri; obinem T(n)=(3n-3)/2=(3n+1)/2-2=3n/2-2.
n concluzie, timpul de calcul este T(n)=3n/2-2.

Propoziia 2. Algoritmul de mai sus este optimal.


Considerm urmtoarele mulimi i cardinalul lor:
- A= mulimea elementelor care nu au participat nc la comparri; a=|A|;
- B= mulimea elementelor care au participat la comparri i au fost totdeauna
mai mari dect elementele cu care au fost comparate; b=|B|;
- C= mulimea elementelor care au participat la comparri i au fost totdeauna
mai mici dect elementele cu care au fost comparate; c=|C|;
- D= mulimea elementelor care au participat la comparri i au fost cel puin o
dat mai mari i cel puin o dat mai mici dect elementele cu care au fost
comparate; d=|D|.
Numim configuraie un quadruplu (a,b,c,d). Problema const n
determinarea numrului de comparri necesare pentru a trece de la quadruplul
(n,0,0,0) la quadruplul (0,1,1,n-2).
Considerm un algoritm arbitrar care rezolv problema i artm c el
efectueaz cel puin 3n/2-2 comparri.

12

1. DESPRE ALGORITMI

S analizm trecerea de la o configuraie oarecare (a,b,c,d) la


urmtoarea. Este evident c nu are sens s efectum comparri n care intervine
vreun element din D. Apar urmtoarele situaii posibile:
1) Compar dou elemente din A: se va trece n configuraia (a-2,b+1,c+1,d) .
2) Compar dou elemente din B: se va trece n configuraia (a,b-1,c,d+1) .
3) Compar dou elemente din C: se va trece n configuraia (a,b,c-1,d+1) .
4) Se compar un element din A cu unul din B. Sunt posibile dou situaii:
- elementul din A este mai mic: se trece n configuraia (a-1,b,c+1,d);
- elementul din A este mai mare: se trece n configuraia (a-1,b,c,d+1).
Cazul cel mai defavorabil este primul, deoarece implic o deplasare "mai lent"
spre dreapta a componentelor quadruplului. De aceea vom lua n considerare
acest caz.
5) Se compar un element din A cu unul din C. Sunt posibile dou situaii:
- elementul din A este mai mic: se trece n configuraia (a-1,b,c,d+1);
- elementul din A este mai mare: se trece n configuraia (a-1,b+1,c,d).
Cazul cel mai defavorabil este al doilea, deoarece implic o deplasare "mai
lent" spre dreapta a componentelor quadruplului. De aceea vom lua n
considerare acest caz.
6) Se compar un element din B cu unul din C. Sunt posibile dou situaii:
- elementul din B este mai mic: se trece n configuraia (a,b-1,c-1,d+2);
- elementul din B este mai mare: se rmne n configuraia (a,b,c,d).
Cazul cel mai defavorabil este al doilea, deoarece implic o deplasare "mai
lent" spre dreapta a componentelor quadruplului. De aceea vom lua n
considerare acest caz.
Observaie. Cazurile cele mai favorabile sunt cele n care d crete, deci ies
din calcul elemente candidate la a fi cel mai mic sau cel mai mare.
Odat stabilit trecerea de la o configuraie la urmtoarea, ne punem
problema cum putem trece mai rapid de la configuraia iniial la cea final.
Analizm cazul n care n=2k (cazul n care n este impar este propus ca
exerciiu). Trecerea cea mai rapid la configuraia final se face astfel:
- plecm de la (n,0,0,0)=(2k,0,0,0);
- prin k comparri ntre perechi de elemente din A ajungem la (0,k,k,0);
- prin k-1 comparri ntre perechi de elemente din B ajungem la (0,1,k,k1);
- prin k-1 comparri ntre perechi de elemente din C ajungem la (0,1,1,n2).
n total au fost necesare k+(k-1)+(k-1)=3k-2=3n/2-2 comparri.

1.6. Existena algoritmilor

1.6.

13

Existena algoritmilor

Acest aspect este i mai delicat dect precedentele, pentru c necesit o


definiie matematic riguroas a noiunii de algoritm. Nu vom face dect s
prezentm (fr vreo demonstraie) cteva definiii i rezultate. Un studiu mai
amnunit necesit un curs aparte!
ncepem prin a preciza c problema existenei algoritmilor a stat n atenia
matematicienilor nc nainte de apariia calculatoarelor. n sprijinul acestei
afirmaii ne rezumm la a spune c un rol deosebit n aceast teorie l-a jucat
matematicianul englez Alan Turing (1912-1954), considerat printele inteligenei
artificiale.
Deci ce este un algoritm?
Noiunea de algoritm nu poate fi definit dect pe baza unui limbaj sau a
unei maini matematice abstracte.
Prezentm n continuare o singur definiie, care are la baz limbajul S
care opereaz asupra numerelor naturale.
Un program n limbajul S folosete variabilele:
- x1,x2,... care constituie datele de intrare (nu exist instruciuni de citire);
- y (n care va aprea rezultatul prelucrrilor);
- z1,z2,... care constituie variabile de lucru.
Variabilele y,z1,z2,... au iniial valoarea 0.
Instruciunile pot fi etichetate (nu neaprat distinct) i au numai
urmtoarele forme, n care v este o variabil, iar L este o etichet:
 vv+1 { valoarea variabilei v crete cu o unitate }
 vv-1 { valoarea variabilei v scade cu o unitate dac era strict pozitiv }
 if v>0 goto L { se face transfer condiionat la prima instruciune cu
eticheta L, dac o astfel de instruciune exist; n caz contrar programul se
termin }.
Programul se termin fie dac s-a executat ultima instruciune din
program, fie dac se face transfer la o instruciune cu o etichet inexistent.

Observaii:
faptul c se lucreaz numai cu numere naturale nu este o restricie, deoarece n
memorie exist doar secvene de bii (interpretate n diferite moduri);
nu intereseaz timpul de executare a programului, ci numai existena sa;

14

1. DESPRE ALGORITMI

dac rezultatul dorit const din mai multe valori, vom scrie cte un program
pentru calculul fiecreia dintre aceste valori;
programul vid corespunde calculului funciei identic egal cu 0: pentru orice
x1,x2,... valoarea de ieire a lui y este 0 (cea iniial).

Este natural o nencredere iniial n acest limbaj, dac l comparm cu


limbajele evoluate din ziua de azi. Se poate ns demonstra c n limbajul S se pot
efectua calcule "orict" de complexe asupra numerelor naturale.
Teza lui Church (1936). Date fiind numerele naturale x1,x2,...,xn,
numrul y poate fi "calculat" pe baza lor dac i numai dac exist un program
n limbajul S care pentru valorile de intrare x1,x2,...,xn produce la
terminarea sa valoarea y.
Cu alte cuvinte, nelegem prin algoritm ce calculeaz valoarea y plecnd
de la valorile x1,x2,...,xn un program n limbajul S care realizeaz acest lucru.
Exist mai multe definiii ale noiunii de algoritm, bazate fie pe calculul cu
numere naturale fie pe calcul simbolic, folosind fie limbaje de programare fie
maini matematice, dar toate s-au dovedit a fi echivalente (cu cea de mai sus)!
Mai precizm c orice program n limbajul S poate fi codificat ca un
numr natural (n particular mulimea acestor programe este numrabil).
Numim problem nedecidabil o problem pentru care nu poate fi elaborat
un algoritm. Definirea matematic a noiunii de algoritm a permis detectarea de
probleme nedecidabile. Cteva dintre ele sunt urmtoarele:
1) Problema opririi programelor: pentru orice program i orice valori de intrare
s se decid dac programul se termin.
2) Problema opririi programelor (variant): pentru un program dat s se decid
dac el se termin pentru orice valori de intrare.
3) Problema echivalenei programelor: s se decid pentru orice dou programe
dac sunt echivalente (produc aceeai ieire pentru aceleai date de intrare).
n continuare vom lucra cu noiunea de algoritm n accepiunea sa uzual,
aa cum n liceu (i la unele faculti) se lucreaz cu numerele reale, fr a se
prezenta o definiie riguroas a lor.
Am dorit ns s evideniem c exist probleme nedecidabile i c (uimitor
pentru unii) studiul existenei algoritmilor a nceput nainte de apariia
calculatoarelor.

2
2.1.
-

ARBORI

Grafuri

Numim graf neorientat o pereche G=(V,M), unde:


V este o mulime finit i nevid de elemente numite vrfuri (noduri);
M este o mulime de perechi de elemente distincte din V, numite muchii. O
muchie avnd vrfurile i i j (numite extremitile sale) este notat prin
(i,j) sau (j,i).

Un subgraf al lui G este un graf G'=(V',M') unde V'V, iar M' este
format din toate muchiile lui G care unesc vrfuri din V'.
Un graf parial al lui G este un graf G'=(V,M') cu M'M.
Numim drum o succesiune de muchii (i1,i2),(i2,i3),...,(ik-1,ik),
notat i prin (i1,i2,...,ik). Dac toate vrfurile drumului sunt distincte,
atunci el se numete drum elementar.
Un ciclu elementar este un drum (i1,i2,...,ik,i1), cu
(i1,i2,...,ik) drum elementar i k3. Un ciclu este un drum
(i1,i2,...,ik,i1) care conine cel puin un ciclu elementar.
1
2
Exemplul 1. n graful alturat:
- (1,2,5,4) este un drum de la 1 la 4;
3
- (5,2,1,4,5) este un ciclu elementar;
- (1,2,1) nu este un ciclu.
5
4
Un graf neorientat se numete conex dac oricare dou vrfuri ale sale sunt
unite printr-un drum.
n cazul unui graf neconex, se pune problema determinrii componentelor
sale conexe; o component conex este un subgraf conex maximal.
Descompunerea n componente conexe determin att o partiie a vrfurilor, ct i
a muchiilor.
Exemplul 2. Graful urmtor are dou componente conexe i anume
subgrafurile determinate de submulimile de vrfuri {1,2,3}, {4}, {5,6}.

2. ARBORI

16

5
4

n cele ce urmeaz vom nota prin n numrul vrfurilor, iar prin m numrul
muchiilor unui graf: n=|V|, m=|M|. n analiza complexitii n timp a
algoritmilor pe grafuri, aceasta va fi msurat n funcie de m+n, adic se va ine
cont att de numrul vrfurilor ct i de cel al muchiilor.
Prin gradul grad(i) al unui vrf i nelegem numrul muchiilor care l au
ca extremitate.
Un graf orientat este tot o pereche G=(V,M), deosebirea fa de grafurile
neorientate constnd n faptul c elementele lui M sunt perechi ordonate de vrfuri
numite arce; altfel spus, orice arc (i,j) are stabilit un sens de parcurgere i
anume de la extremitatea sa iniial i la extremitatea sa final j.
Noiunile de drum, drum elementar, ciclu i ciclu elementar de la grafurile
neorientate se transpun n mod evident la grafurile orientate, cu singura observaie
c n loc de ciclu vom spune circuit.
Pentru un vrf i:
- gradul interior grad-(i) este numrul arcelor ce sosesc n i;
- gradul exterior grad+(i) este numrul arcelor ce pleac din i.

2.2.

Arbori

Numim arbore un graf neorientat conex i fr cicluri.


Aceasta nu este singurul mod n care putem defini arborii. Cteva definiii
echivalente apar n urmtoarea teorem, expus fr demonstraie.
Teorem. Fie G un graf cu n1 vrfuri. Urmtoarele afirmaii sunt
echivalente:
1) G este un arbore;
2) G are n-1 muchii i nu conine cicluri;
3) G are n-1 muchii i este conex;
4) oricare dou vrfuri din G sunt unite printr-un unic drum;
5) G nu conine cicluri i adugarea unei noi muchii produce un unic ciclu
elementar;
6) G este conex, dar devine neconex prin tergerea oricrei muchii.

2.2. Arbori

17

n foarte multe probleme referitoare la arbori este pus n eviden un vrf


al su, numit rdcin. Alegerea unui vrf drept rdcin are dou consecine:

Arborele poate fi aezat pe niveluri astfel:


rdcina este aezat pe nivelul 0;
pe fiecare nivel i sunt plasate vrfurile pentru care lungimea drumurilor care
le leag de rdcin este i;
- se traseaz muchiile arborelui.
Aceast aezare pe niveluri face mai intuitiv noiunea de arbore, cu
precizarea c n informatic "arborii cresc n jos".
Exemplul 3. Considerm urmtorul arbore i modul n care el este aezat
pe niveluri prin alegerea vrfului 5 drept rdcin.
5
0
1
2
4
6
1
3
6
4
8
7
2
9 3
2
9
5
7
10
3
10
1
8

Arborele poate fi considerat un graf orientat, stabilind pe fiecare muchie


sensul de la nivelul superior ctre nivelul inferior.

Reprezentarea pe niveluri a arborilor face ca noiunile de fii (descendeni)


ai unui vrf, precum i de tat al unui vrf s aib semnificaii evidente. Un vrf
fr descendeni se numete frunz.

2.3.

Arbori binari

Un arbore binar este un arbore n care orice vrf are cel mult doi
descendeni, cu precizarea c se face distincie ntre descendentul stng i cel
drept. Rezult c un arbore binar nu este propriu-zis un caz particular de arbore.
Primele probleme care se pun pentru arborii binari (ca i pentru arborii
oarecare i pentru grafuri, aa cum vom vedea mai trziu) sunt:
- modul de reprezentare;
- parcurgerea lor.

2. ARBORI

18

Forma standard de reprezentare a unui arbore const n:


a preciza rdcina rad a arborelui;
a preciza pentru fiecare vrf i tripletul st(i), dr(i) i info(i), unde
acestea sunt respectiv descendentul stng, descendentul drept i informaia
ataat vrfului.
Trebuie stabilit o convenie pentru lipsa unuia sau a ambilor descendeni;
alegem specificarea lor prin simbolul .

Exemplul 4. Considerm de exemplu urmtorul arbore binar:


1

2
3

8
5

Presupunnd c informaia ataat fiecrui vrf este chiar numrul su de


ordine, avem:
- rad=1;
- st=(2,3,4,,6,,,,);
- dr=(8,5,,,7,,,9,);
- info=(1,2,3,4,5,6,7,8,9).
Dintre diferitele alte reprezentri posibile, mai menionm doar pe cea care
se reduce la vectorul su tata i la vectorul info. Pentru exemplul de mai sus:
tata=(,1,2,3,2,5,5,1,8).
Problema parcurgerii unui arbore binar const n identificarea unei
modaliti prin care, plecnd din rdcin i mergnd pe muchii, s ajungem n
toate vrfurile; n plus, atingerea fiecrui vrf este pus n eviden o singur
dat: spunem c vizitm vrful respectiv. Aciunea ntreprins la vizitarea unui
vrf depinde de problema concret i poate fi de exemplu tiprirea informaiei
ataate vrfului.
Distingem trei modaliti standard de parcurgere a unui arbore binar:

2.3. Arbori binari

19

Parcurgerea n preordine
Se parcurg recursiv n ordine: rdcina, subarborele stng, subarborele

drept.
Ilustrm acest mod de parcurgere pentru exemplul de mai sus, figurnd
ngroat rdcinile subarborilor ce trebuie dezvoltai:
1
1, 2, 8
1, 2, 3, 5, 8, 9
1, 2, 3, 4, 5, 6, 7, 8, 9
Concret, se execut apelul preord(rad) pentru procedura:
procedure preord(x)
if x=
then
else vizit(x); preord(st(x)); preord(dr(x))
end

Parcurgerea n inordine
Se parcurg recursiv n ordine: subarborele stng, rdcina, subarborele

drept.
Ilustrm acest mod de parcurgere pentru Exemplul 4:
1
2, 1, 8
3, 2, 5, 1, 8, 9
4, 3, 2, 6, 5, 7, 1, 8, 9
Concret, se execut apelul inord(rad) pentru procedura:
procedure inord(x)
if x=
then
else inord(st(x)); vizit(x); inord(dr(x))
end

Parcurgerea n postordine

Se parcurg recursiv n ordine; subarborele stng, subarborele drept,


rdcina.
Ilustrm parcurgerea n postordine pentru Exemplul 4:
1
2, 8, 1
3, 5, 2, 9, 8, 1
4, 3, 6, 7, 5, 2, 9, 8, 1

2. ARBORI

20

Concret, se execut apelul postord(rad) pentru procedura:


procedure postord(x)
if x=
then
else postord(st(x)); postord(dr(x)); vizit(x)
end

2.4.

Aplicaii ale arborilor binari


Prezentm n acest paragraf doi algoritmi de sortare, care folosesc arbori

binari.
Fie a=(a1,...,an) vectorul care trebuie sortat (ordonat cresctor).

Sortarea cu ansamble

Metoda sortrii de ansamble va folosi o reprezentare implicit a unui


vector ca arbore binar. Acest arbore este construit succesiv astfel:
- rdcina este 1;
- pentru orice vrf i, descendenii si stng i drept sunt 2i i 2i+1 (cu condiia
ca fiecare dintre aceste valori s nu depeasc pe n). Rezult c tatl oricrui
vrf i este tata(i)=i/2.
Evident, fiecrui vrf i i vom ataa eticheta ai.
Pentru 2k-1n<2k arborele va avea k niveluri, dintre care numai ultimul
poate fi incomplet (pe fiecare nivel i<k-1 se afl exact 2i vrfuri).
0
1

k-2
k-1

Vectorul a se numete ansamblu dac pentru orice i avem aia2i i


aia2i+1 (dac fiii exist).

2.4. Aplicaii ale arborilor binari

21

S presupunem c subarborii de rdcini 2i i 2i+1 sunt ansamble. Ne


propunem s transformm arborele de rdcin i ntr-un ansamblu. Ideea este de a
retrograda valoarea ai pn ajunge ntr-un vrf ai crui descendeni au valorile
mai mici dect ai. Acest lucru este realizat de procedura combin.
i

2i

procedure combin(i,n)
j 2i; b ai
while jn
if j<n & aj<aj+1 then jj+1
if b>aj
then aj/2 b; exit
else aj/2 aj; j 2j
aj/2 b
end

2i+1

ans

ans

Timpul de executare pentru procedura combin este O(k)=O(log n).


Exemplul 5. Pentru:
n=12, a=(3,12,11,6,8,9,10,1,5,2,4,7) i i=1, calculele decurg dup
cum urmeaz:
1

n
12

12

11

10

11

12

i
1

j
2
4
5
10
11
22

b
3

a112
a28
a54
a113

7 10

Sortarea vectorului a se va face prin apelul succesiv al procedurilor


creare i sortare prezentate n continuare.

2. ARBORI

22

Procedura creare transform vectorul ntr-un ansamblu; n particular n


a1 se obine cel mai mare element al vectorului.
Procedura sortare lucreaz astfel:
- pune pe a1 pe poziia n i reface ansamblul format din primele n-1 elemente;
- pune pe a1 pe poziia n-1 i reface ansamblul format din primele n-2
-

elemente;
etc.

procedure creare
for i=n/2,1,-1
combin(i,n)
end

procedure sortare
for i=n,2,-1
a1 ai; combin(1,i-1)
end

Timpul total de lucru este de ordinul O(n log n).


Aa cum am menionat chiar de la nceput, structura de arbore este
implicit i este menit doar s clarifice modul de lucru al algoritmului: calculele
se refer doar la componentele vectorului.
.

Arbori de sortare

Un arbore de sortare este un arbore binar n care pentru orice vrf


informaia ataat vrfului este mai mare dect informaiile vrfurilor din
subarborele su stng i mai mic dect informaiile vrfurilor din subarborele su
drept.
Un exemplu de arbore de sortare este urmtorul:
11
20

5
7

17

15
18
Observaie. Parcurgerea n inordine a unui arbore de cutare produce
informaiile ataate vrfurilor n ordine cresctoare.
Fie a=(a1,...an) un vector ce trebuie ordonat cresctor. Conform
observaiei de mai sus, este suficient s crem un arbore de sortare n care
informaiile vrfului s fie tocmai elementele vectorului. Pentru aceasta este
suficient s precizm modul n care, prin adugarea unei noi valori, se obine tot
un arbore de sortare.

2.4. Aplicaii ale arborilor binari

23

Pentru exemplul considerat:


adugarea valorii 6 trebuie s conduc la crearea unui nou vrf, cu informaia
6 i care este descendent stng al vrfului cu informaia 7;
adugarea valorii 16 trebuie s conduc la crearea unui nou vrf, cu informaia
16 i care este descendent drept al vrfului cu informaia 15.

Presupunem c un vrf din arborele de sortare este o nregistrare sau obiect


de tipul varf, ce conine cmpurile:
- informaia info ataat vrfului;
- descendentul stng st i descendentul drept dr (lipsa acestora este marcat,
ca de obicei, prin ).
Crearea unui nou vrf se face prin apelul funciei varf_nou, care ntoarce
un nou vrf:
function varf_nou(info)

crem un nou obiect/ o nou nregistrare x n care informaia este info, iar
descendentul stng i cel drept sunt ;
return x
end

Inserarea unei noi valori val (n arborele de rdcin rad) se face prin
apelul adaug(rad,val), unde funcia adaug ntoarce o nregistrare i are
forma:
function adaug(x,val) { se insereaz val n subarborele de rdcin x}
if x=
then return varf_nou(val)
else if val<info(x)
then st(x) adaug(st(x),val)
else dr(x) adaug(dr(x),val)
return x
end

Programul principal ntreprinde urmtoarele aciuni:


citete valorile ce trebuie ordonate i le insereaz n arbore;
parcurge n inordine arborele de sortare; vizitarea unui vrf const, de
exemplu, n tiprirea informaiei ataate.

Prezentm programul n Java (clasa IO.java, folosit pentru citire i


scriere, este descris n anex) :

2. ARBORI

24

class elem {
int c; elem st,dr;
elem() { }
elem(int ch) { c=ch; st=null; dr=null; }
elem adaug(elem x, int ch) {
if (x==null) x=new elem(ch);
else if (ch<x.c) x.st=adaug(x.st,ch);
else x.dr=adaug(x.dr,ch);
return x;
}
String parcurg(elem x) {
if (x==null) return("");
else return( parcurg(x.st) + x.c + " " + parcurg(x.dr));
}
}
class Arbsort {
public static void main(String arg[]) {
elem rad=null; double val;
elem Ob = new elem(); val = IO.read();
while ( ! Double.isNaN(val) )
{ rad = Ob.adaug(rad,(int) val); val = IO.read(); }
IO.writeln(Ob.parcurg(rad));
}
}

2.5.

Arbori oarecare

Continum cu studiul arborilor oarecare.


Primele probleme care se pun sunt aceleai ca pentru arborii binari:
modalitile de reprezentare i de parcurgere.
Exemplul 6. Considerm urmtorul arbore:
1
2
5

10 11

3
7

12

13

0
1

2.5. Arbori oarecare

25

Se consider c arborele este aezat pe niveluri i c pentru fiecare vrf


exist o ordine ntre descendenii si.
Modul standard de reprezentare al unui arbore oarecare const n a
memora rdcina, iar pentru fiecare vrf i informaiile:
- info(i) = informaia ataat vrfului;
- fiu(i) = primul vrf dintre descendenii lui i;
- frate(i) = acel descendent al tatlui lui i, care urmez imediat dup i.
Ca i pentru arborii binari, lipsa unei legturi este indicat prin .
Pentru arborele din Exemplul 6:
fiu=(2,5,7,8,10,11,,,,,,,);
frate=(,3,4,,6,,,9,,,12,13,).

O alt modalitate de reprezentare const n a memora pentru fiecare vrf


tatl su. Aceast modalitate este incomod pentru parcurgerea arborilor, dar se
dovedete util n alte situaii, care vor fi prezentate n continuare.
n unele cazuri este util s memorm pentru fiecare vrf att fiul i fratele
su, ct i tatl su.


Parcurgerea n preordine

Se parcurg recursiv n ordine rdcina i apoi subarborii care au drept


rdcin descendenii si. Pentru Exemplul 6:
1
1,2,3,4
1,2,5,6,3,7,4,8,9
1,2,5,10,6,11,12,13,3,7,4,8,9.
Concret, executm apelul Apreord(rad) pentru procedura:
procedure Apreord(x)
if x=
then
else vizit(x); Apreord(fiu(x)); Apreord(frate(x))
end

Ca aplicaie, s presupunem c informaiile ataate vrfurilor sunt funcii


de diferite ariti (aritatea unei funcii este numrul variabilelor de care depinde; o
funcie de aritate 0 este o constant).

2. ARBORI

26

Pentru Exemplul 6, vectorul de aritate este:


aritate=(3,2,1,2,1,3,0,0,0,0,0,0,0).
Rezultatul 1 2 5 10 6 11 12 13 3 7 4 8 9 al parcurgerii n

preordine este o form fr paranteze (dar la fel de consistent) a scrierii expresiei


funcionale:
1(2(5(10),6(11,12,13)),3(7),4(8,9))

Aceast form se numete forma polonez direct.




Parcurgerea n postordine

Se parcurg recursiv n ordine subarborii rdcinii i apoi rdcina. Pentru


Exemplul 5:
1
2,3,4,1
5,6,2,7,3,8,9,4,1
10,5,11,12,13,6,2,7,3,8,9,4,1.
Concret, executm apelul Apostord(rad) pentru procedura:
procedure Apostord(x)
if x=
then
else yfiu(x);
while y<>
Apostord(y); yfrate(y)
vizit(x)
end

Relum aplicaia de la parcurgerea n inordine. Dorim s calculm


valoarea expresiei funcionale, cunoscnd valorile frunzelor (funciilor de aritate
0). Este evident c trebuie s parcurgem arborele n postordine.


Parcurgerea pe niveluri

Se parcurg vrfurile n ordinea distanei lor fa de rdcin, innd cont de


ordinea n care apar descendenii fiecrui vrf. Pentru Exemplul 5:
1,2,3,4,5,6,7,8,9,10,11,12,13.
Pentru implementare vom folosi o coad C, n care iniial apare numai
rdcina. Atta timp ct coada este nevid, vom extrage primul element, l vom
vizita i vom introduce n coad descendenii si:

2.5. Arbori oarecare

27

C ; C rad
while C
x C; vizit(x);
y fiu(x);
while y
y C ; y frate(y)

Parcurgerea pe niveluri este n general util atunci cnd se caut vrful


care este cel mai apropiat de rdcin i care are o anumit proprietate/informaie.

3
3.1.

GRAFURI

Parcurgerea DF a grafurilor neorientate

Fie G=(V,M) un graf neorientat. Ca de obicei, notm n=|V| i m=|M|.


Parcurgerea n adncime a grafurilor (DF = Depth First) generalizeaz
parcurgerea n preordine a arborilor oarecare. Eventuala existen a ciclurilor
conduce la necesitatea de a marca vrfurile vizitate. Ideea de baz a algoritmului
este urmtoarea: se pleac dinr-un vrf i0 oarecare, apelnd procedura DF pentru
acel vrf. Orice apel de tipul DF(i) prevede urmtoarele operaii:
- marcarea vrfului i ca fiind vizitat;
- pentru toate vrfurile j din lista Li a vecinilor lui i se execut apelul DF(j)
dac i numai dac vrful j nu a fost vizitat.
Simpla marcare a unui vrf ca fiind sau nu vizitat poate fi nlocuit, n
perspectiva unor aplicaii prezentate n continuare, cu atribuirea unui numr de
ordine fiecrui vrf; mai precis, n nrdf(i), iniial egal cu 0, va fi memorat al
ctelea este vizitat vrful i; nrdf(i) poart numele de numrul (de ordine) DF
al lui i.
Este evident c plecnd din vrful i0 se pot vizita numai vrfurile din
componenta conex a lui i0. De aceea, n cazul n care graful nu este conex, dup
parcurgerea componentei conexe a lui i0 vom repeta apelul DF pentru unul dintre
eventualele vrfuri nc neatinse.
procedure DF(i)
ndf ndf+1; nrdf(i) ndf; vizit(i);
for toi jLi
if nrdf(j)=0 then DF(j)

Programul principal este:


citete graful;
ndf0;
for i=1,n
nrdf(i) 0
for i=1,n
if nrdf(i)=0 then DF(i)
write(nrdf)

3.1. Parcurgerea DF a grafurilor neorientate

29

Observaie. Dac dorim doar s determinm dac un graf este conex, vom
nlocui al doilea ciclu for din programul principal prin:
DF(1);
if ndf=n then write(CONEX)
else write(NECONEX);

Observaie. Parcurgerea DF mparte muchiile grafului n:


muchii de avansare: sunt acele muchii (i,j) pentru care n cadrul apelului
DF(i) are loc apelul DF(j). Aceste muchii formeaz un graf parial care este
o pdure: fiecare vrf este vizitat exact o dat, deci nu exist un ciclu format
din muchii de avansare.
muchii de ntoarcere: sunt acele muchii ale grafului care nu sunt muchii de
avansare.

Determinarea mulimilor A i I a muchiilor de avansare i ntoarcere,


precum i memorarea arborilor pariali din pdurea DF se poate face astfel:
-

n programul principal se fac iniializrile:

A ; I ;
for i=1,n
tata(i) 0;

instruciunea if din procedura DF devine:


if nrdf(j)=0
then AA{(i,j)}; tata(j) i; DF(j)
else if tata(j) i
then II{(i,j)};
Exemplu. Pentru graful:
2

3
1

9
7

cu urmtoarele liste ale vecinilor vrfurilor:


L1={4,2,3};
L4={1,2,5};
L7={9};

L2={1,4};
L5={3,4};
L8={6}

L3={1,5};
L6={8,9};
L9={6,7}

3. GRAFURI

30

pdurea DF este format din urmtorii arbori pariali corespunztori


componentelor conexe:
1
6
4

9
8

5
7
3

Timpul cerut de algoritmul de mai sus este O(max{n,m})=O(n+m), deci


algoritmul este liniar, deoarece:
- pentru fiecare vrf i, apelul DF(i) are loc exact o dat;
- executarea unui apel DF(i) necesit un timp proporional cu
grad(i)=|Li|; n consecin timpul total va fi proporional cu m=|M|.
Propoziie. Dac (i,j) este muchie de ntoarcere, atunci i este
descendent al lui j n arborele parial ce conine pe i i j.
Muchia (i,j) este detectat ca fiind muchie de ntoarcere n cadrul
executrii apelului DF(i), deci nrdf(j)<nrdf(i). Deoarece exist muchie
ntre vrfurile i i j, rezult c n timpul executrii lui DF(j) va fi vizitat i
vrful i, deci i este descendent al lui j.
Propoziia de mai sus spune c muchiile de ntoarcere leag totdeauna
dou vrfuri situate pe aceeai ramur a pdurii pariale DF. n particular, nu
exist muchii de traversare (care s lege doi descendeni ai aceluiai vrf dintr-un
arbore DF).
Observaie. Un graf este ciclic (conine cel puin un ciclu) dac i numai
dac n timpul parcurgerii sale n adncime este detectat o muchie de ntoarcere.
Aplicaie. S se determine dac un graf este ciclic i n caz afirmativ s se
identifice un ciclu.
Vom memora pdurea format din muchiile de avansare cu ajutorul
vectorului tata i n momentul n care este detectat o muchie de ntoarcere
(i,j) vom lista drumul de la i la j format din muchii de avansare i apoi muchia
(j,i).
Procedura DF va fi modificat astfel:

3.1. Parcurgerea DF a grafurilor neorientate

31

procedure DF(i)
ndf ndf+1; nrdf(i) ndf; vizit(i);
for toi jLi
if nrdf(j)=0
then tata(j) i; DF(j)
else if tata(i)j
then k i;
while kj
write(k,tata(k)); k tata(k);
write(j,i); stop
end.

3.2.

Observaii:
dac notm prin nrdesc(i) numrul descendenilor lui i n subarborele
de rdcin i, aceast valoare poate fi calculat plasnd dup ciclul for
din procedura DF instruciunea nrdesc(i)ndf-nrdf(i)+1;
un vrf j este descendent al vrfului i n subarborele DF de rdcin i
nrdf(i)nrdf(j)<nrdf(i)+nrdesc(i).

O aplicaie: Problema brfei

Se consider n persoane. Fiecare dintre ele emite o brf care trebuie


cunoscut de toate celelalte persoane.
Prin mesaj nelegem o pereche de numere (i,j) cu i,j{1,...,n} i
cu semnificaia c persoana i transmite persoanei j brfa sa, dar i toate brfele
care i-au parvenit pn la momentul acestui mesaj.
Se cere una dintre cele mai scurte succesiuni de mesaje prin care toate
persoanele afl toate brfele.
Cu enunul de mai sus, o soluie este imediat i const n succesiunea de
mesaje: (1,2),(2,3),...,(n-1,n),(n,n-1),(n-1,n-2),...,(2,1) .
Sunt transmise deci n-2 mesaje. Dup cum vom vedea mai jos, acesta este
numrul minim de mesaje prin care toate persoanele afl toate brfele.
Problema se complic dac exist persoane care nu comunic ntre ele
(sunt certate) i deci nu-i vor putea transmite una alteia mesaje.
Aceast situaie poate fi modelat printr-un graf n care vrfurile
corespund persoanelor, iar muchiile leag persoane care nu sunt certate ntre ele.

32

3. GRAFURI

Vom folosi matricea de adiacen a de ordin n n care aij este 0 dac


persoanele i i j sunt certate ntre ele (nu exist muchie ntre i i j) i 1 n caz
contrar.
Primul pas va consta n detectarea unui arbore parial; pentru aceasta vom
folosi parcurgerea DF. Fiecrei persoane i i vom ataa variabila boolean vi,
care este true dac i numai dac vrful corespunztor a fost atins n timpul
parcurgerii; iniial toate aceste valori sunt false. Vom pune aij=2 pentru toate
muchiile de avansare.
vi false, i=1,...n
ndf 0; DF(1)
if ndf<n
then write('Problema nu are soluie (graf neconex)')
else rezolv problema pe arborele parial obinut

unde procedura DF are forma cunoscut:


procedure DF(i)
vi true; ndf ndf+1
for j=1,n
if aij=1 & not vj
then aij 2; DF(j)
end

S observm c n acest mod am redus problema de la un graf la un


arbore! Descriem n continuare modul n care rezolvm problema pe acest arbore
parial, bineneles n ipoteza c problema are soluie (graful este conex).
Printr-o parcurgere n postordine, n care vizitarea unui vrf const n
transmiterea de mesaje de la fiii si la el, rdcina (presupus a fi persoana 1) va
ajunge s cunoasc toate brfele. Aceasta se realizeaz prin apelul postord(1),
unde procedura postord are forma:
procedure postord(i)
for j=1,n
if aij=2
then postord(j); write(j,i)
end

n continuare, printr-o parcurgere n preordine a arborelui DF, mesajele


vor circula de la rdcin ctre frunze. Vizitarea unui vrf const n transmiterea
de mesaje fiilor si. Pentru aceasta executm apelul preord(1), unde procedura
preord are forma:

3.2. O aplicaie: Problema brfei

33

procedure preord(i)
for j=1,n
if aij=2
then write(i,j); preord(j);
end

Observm c att la parcurgerea n postordine, ct i la cea n preordine au


fost listate n-1 perechi (mesaje), deoarece un arbore cu n vrfuri are n-1 muchii.
Rezult c soluia de mai sus const ntr-o succesiune de 2n-2 mesaje. Mai
rmne de demonstrat c acesta este numrul minim posibil de mesaje care
rezolv problema.
Propoziie. Orice soluie pentru problema brfei conine cel puin 2n-2
mesaje.
S considerm o soluie oarecare pentru problema brfei.
Punem n eviden primul mesaj prin care o persoan a ajuns s cunoasc
toate brfele; fie k aceast persoan. Deoarece celelalte persoane trebuie s le fi
emis, nseamn c pn acum au fost transmise cel puin n-1 mesaje. Dar k este
prima persoan care a aflat toate brfele, deci celelalte trebuie s mai afle cel
puin o brf. Rezult c n continuare trebuie s apar nc cel puin n-1 mesaje.
n concluzie, soluia considerat este format din cel puin 2n-2 mesaje.

3.3.

Circuitele fundamentale ale unui graf

Fie G=(V,M) un graf neorientat conex.


Fie A=(V,M) un arbore parial al lui G. Muchiile din M\M sunt muchii de
ntoarcere, numite i corzi.
Pentru fiecare coard exist un unic drum, format numai din muchii din
M, ce unete extremitile corzii. mpreun cu coarda, acest drum formeaz un
ciclu numit ciclu fundamental.
Fie G1=(X1,M1) i G2=(X2,M2) dou grafuri. Definim suma lor circular
ca fiind graful:
G1 G2 = (X1X2,M1M2\M1M2)

Observaii:
1) Operaia este comutativ i asociativ;
2) Dac M1 i M2 reprezint cicluri, atunci M1 M2 este tot un ciclu sau o
reuniune disjunct (n privina muchiilor) de cicluri:
Exemple.

3. GRAFURI

34

8
8
(1,2,4,7,6,1) (2,3,8,7,4,2) = (1,2,3,8,7,6,1)
1

8
5
6
8
7
7
(1,5,6,2,4,3,2,1) (7,8,4,3,2,4,7) = (1,5,6,2,1) (7,8,4,7)

Teorem. Pentru un graf i un arbore parial A al su date, ciclurile


fundamentale formeaz o baz, adic sunt ndeplinite condiiile:
1) orice ciclu se poate exprima ca sum circular de cicluri fundamentale;
2) nici un ciclu fundamental nu poate fi exprimat ca sum circular de cicluri
fundamentale.
Exemplu. Considerm urmtorul graf i un arbore parial al su:
2
3

Arborele parial A:

Muchiile de ntoarcere sunt (2,3), (3,4), (2,5), (4,5). Ciclul (1,2,5,4,3,1) se


poate scrie ca o sum circular de cicluri fundamentale astfel:
2
2
1

=
1

5
4

3.3. Circuitele fundamentale ale unui graf

35

Demonstraie.
Considerm un ciclu n G, ale crui muchii sunt partiionate n
C={e1,...,ek}{ek+1,...,ej} unde e1,...,ek sunt corzi, iar ek+1,...,ej
sunt muchii din A.
Fie C(e1),...,C(ek) ciclurile fundamentale din care fac parte
e1,...,ek. Fie C=C(e1)... C(ek). Vom demonstra c C=C (sunt formate
din aceleai muchii).
Presupunem c CC. Atunci CC. S observm c att C ct i C
conin corzile e1,...,ek.
Conform unei observaii de mai sus, C i apoi CC sunt cicluri sau
reuniuni disjuncte de cicluri. Cum att C ct i C conin corzile e1,...,ek i n
rest muchii din A, rezult c CC conine numai muchii din A, deci nu poate
conine un ciclu. Contradicie.
Fie un ciclu fundamental care conine coarda e. Fiind singurul ciclu
fundamental ce conine e, el nu se va putea scrie ca sum circular de alte cicluri
fundamentale.
Consecin. Baza format din circuitele fundamentale are ordinul mn+1.
Determinarea mulimii ciclurilor fundamentale
Printr-o parcurgere a arborelui A, putem stabili pentru el legtura tata.
Atunci pentru orice coard (i,j) procedm dup cum urmeaz:
1) Determinm vectorii:
u = (u1=i, u2=tata(u1), ... , unu=tata(unu-1)=rad)
v = (v1=j, v2=tata(v1), ... , vnv=tata(vnv-1)=rad).
2) Parcurgem simultan vectorii u i v de la dreapta la stnga i determinm
cel mai mic indice k cu uk=vk.

Atunci ciclul cutat este:


u1=i, u2, ... , uk=vk, vk-1, ... , v1=j, i
Observm c pentru fiecare coard, timpul este O(n).

3.4.

Componentele biconexe ale unui graf neorientat

Fie G=(V,M) un graf neorientat, conex.


Un vrf i se numete punct de articulaie dac prin ndeprtarea sa i a
muchiilor adiacente, graful nu mai rmne conex.
Un graf G=(V,M) se numete biconex dac nu are puncte de articulaie.
Dac G nu este biconex, se pune n mod natural problema determinrii

3. GRAFURI

36

componentelor sale biconexe, unde prin component biconex (sau bloc) se


nelege un subgraf biconex maximal.
Exemplu: Componentele biconexe ale grafului:
2

3
1

9
5

4
6

8
8
7

n care elementele din listele vecinilor apar n ordine cresctoare, sunt


urmtoarele:
2

5
1

S observm c descompunerea unui graf n componente biconexe


determin o partiionare a lui M, dar nu a lui V.
Prezentm n continuare un algoritm de complexitate liniar n timp pentru
determinarea componentelor biconexe ale unui graf. Algoritmul se bazeaz pe
parcurgerea DF a grafurilor.
Pentru exemplul de mai sus, parcurgerea DF conduce la urmtorul arbore
parial i la urmtoarele numere de ordine DF ataate vrfurilor (se presupune c
n lista vecinilor unui vrf, acetia apar n ordine cresctoare):
1

6
8
7

nrdf(i)

v(i)

1
2
3
4
5
6
7
8
9

1
2
8
9
3
4
5
6
7

1
1
1
1
1
3
3
6
2

3.4. Componentele biconexe ale unui graf neorientat

37

unde muchiile de ntoarcere au fost figurate punctat. Punctele de articulaie sunt


vrfurile 1 i 5.
Reamintim faptul c muchiile de ntoarcere pot uni doar vrfuri situate pe
aceeai ramur a arborelui DF, deci nu pot fi muchii de traversare:
Punctele de articulaie pot fi caracterizate astfel:
1)
rdcina arborelui DF este punct de articulaie dac i numai dac are
cel puin doi descendeni;
2)
un vrf i diferit de rdcin este punct de articulaie dac i numai dac
are un fiu j cu proprietatea c nici un vrf din subarborele de rdcin
j nu este conectat printr-o muchie de ntoarcere cu un predecesor al lui
i:

NU

Pentru a putea lucra mai uor cu condiia 2), vom asocia fiecrui vrf i o
valoare v(i) definit astfel:
v(i) = min { nrdf(k) | k=i sau k legat printr-o muchie de ntoarcere la i sau la
un descendent al lui i }.
k

sau k=i

Evident, v(i)nrdf(i). Cum orice ciclu elementar este format din


muchii de avansare plus exact o muchie de ntoarcere, rezult c v(i) este
numrul de ordine DF al vrfului k cel mai apropiat de rdcin care se afl ntrun acelai ciclu elementar cu i.

3. GRAFURI

38

Pentru exemplul considerat, valorile lui v apar n tabelul de mai sus.


Condiia 2) se poate reformula acum astfel:
2') un vrf i diferit de rdcin este punct de articulaie dac i numai dac are
un fiu j cu v(j) nrdf(i).
Pentru exemplul considerat, v(8)=6 3=nrdf(5), deci 5 este punct de
articulaie.
Definiia lui v poate fi reformulat, astfel nct s fie adecvat parcurgerii
DF a grafului:
v(i) = min {,,} unde:
= nrdf(i); = min {v(j)|j fiu al lui i};
= min{nrdf(j)|(i,j)I},
cu observaia c corespunde cazului cnd (vezi definiia lui v(i)) k este legat
printr-o muchie de ntoarcere de un descendent al lui i.
Algoritmul de determinare a componentelor biconexe a unui graf conex
folosete o stiv S (iniial vid), n care sunt memorate muchiile componentei
biconexe curente:
procedure Bloc(i)
ndf ndf+1; nrdf(i) ndf; v(i) ndf;
for toi jLi
if (i,j) nu a aprut pn acum n stiva S
then (i,j)S
if nrdf(j)=0 { j devine fiu al lui i n arborele DF }
then tata(j) i; Bloc(j);
if v(j) nrdf(i) { i punct de articulaie }
then repeat
S; write ()
until = (i,j);
v(i) min {v(i),v(j)}
else { (i,j) muchie de ntoarcere }
if jtata(i)
then v(i) min {v(i),nrdf(j)}
end

{ }

{ }

{ }

cu observaia c prin apelul Bloc(j) sunt calculate valorile nrdf i v pentru


toate vrfurile din subarborele de rdcin j n arborele DF.
Programul principal are forma:
ndf 0; S ;

3.4. Componentele biconexe ale unui graf neorientat

39

for i=1,n
nrdf(i)0;
for i=1,n
if nrdf(i)=0 then Bloc(i);

Pentru a demonstra corectitudinea algoritmului este suficient s artm c


dac se ajunge de la un vrf i la un fiu j al su cu v(j)nrdf(i), muchiile care
apar n S ncepnd de la vrf pn la i inclusiv (i,j) formeaz un bloc (o
component biconex).
Vom face demonstraia prin inducie dup numrul b de blocuri.
Dac b=1, inegalitatea v(j)nrdf(i) este satisfcut doar pentru
rdcina i a arborelui DF i pentru j ca unic fiu al su; n momentul verificrii
acestei condiii, stiva conine toate muchiile grafului, iar (i,j) se afl la baza
stivei.
Presupunem afirmaia (c la fiecare extragere din stiv sunt extrase
muchiile unei componente biconexe) adevrat pentru toate grafurile cu mai puin
de b componente biconexe i fie un graf cu b blocuri. Fie i primul vrf pentru
care exist un fiu j cu v(j)nrdf(i). Pn n acest moment nu a fost scoas
nici o muchie din S, iar muchiile din S de deasupra lui (i,j) sunt muchii
incidente cu vrfurile din subarborele de rdcin j, care mpreun cu muchia
(i,j) formeaz o component biconex:
i
j
NU

deoarece din nici un vrf din subarborele de rdcin j nu se urc prin muchii
de ntoarcere mai sus de i.
Dup nlturarea muchiei (i,j) i a celor situate deasupra sa n stiv,
algoritmul se comport ca i cnd blocul nu ar fi existat i deci numrul blocurilor
ar fi fost b-1. Putem aplica acum ipoteza de inducie.
Mai observm c dac notm cu i0 rdcina arborelui DF, atunci pentru
orice fiu j al lui i0 avem v(j)nrdf(i0) deoarece nici o muchie de ntoarcere
cu o extremitate n j nu poate avea cealalt extremitate "mai sus" dect i0. Drept
urmare, dup ce se coboar pe muchia de avansare (i0,j), se continu
parcurgerea DF i se revine n i0, vor fi nlturate din stiv toate muchiile din

3. GRAFURI

40

componenta biconex ce conine (i0,j). n concluzie i situaia n care rdcina


este punct de articulaie este tratat corect.
Algoritmul de mai sus pentru determinarea componentelor biconexe este
liniar (n m+n) deoarece timpul cerut de parcurgerea DF este liniar, iar operaiile
cu stiva necesit un timp proporional cu m=|M|.

3.5.

Parcurgerea DF a grafurilor orientate

Algoritmul este acelai ca la grafuri neorientate.


Arcele de avansare formeaz o pdure constituit din arbori n care toate
arcele au orientarea "de la rdcin ctre frunze", numit "pdure DF".
Exemplu. Pentru graful urmtor, n care listele vecinilor sunt ordonate
cresctor:
10

5
2

11

6
7

obinem pdurea:
1

10
2

5
3
6

i vectorul nrdf = (1,2,3,4,5,6,7,8,9,10,11).

11

3.5. Parcurgerea DF a grafurilor orientate

41

Parcurgerea DF mparte arcele (i,j) n 3 categorii:


1) arce de avansare (pentru ele nrdf(i)<nrdf(j)); ele se mpart n:
1.1) arce componente ale pdurii DF;
1.2) arce ce leag un vrf de un descendent al su care nu este fiu al
su;
2) arce de ntoarcere, ce leag un vrf de un predecesor al su n pdurea DF;
evident nrdf(i)>nrdf(j);
3) arce de traversare: leag dou vrfuri care nu sunt unul descendentul
celuilalt.
Pentru exemplul considerat avem:
1.2) :
(1,6)
2) :
(3,1), (6,4), (11,9)
3) :
(7,2), (8,2), (8,7), (9,1), (11,2), (11,8)
Propoziie.

Pentru

orice

arc

de

traversare

(i,j)

avem

nrdf(i)>nrdf(j).

S presupunem prin absurd c nrdf(i)<nrdf(j). Atunci n momentul


n care s-a ajuns prima dat la i, vrful j nu a fost nc atins. Din modul n care
lucreaz algoritmul, (i,j) va fi arc de avansare; contradicie, deoarece (i,j)
este arc de traversare.
Observaie. Spre deosebire de arcele de traversare, arcele de ntoarcere
determin un circuit elementar (prin adugarea unui astfel de arc la pdurea DF ia
natere un circuit elementar). Putem stabili dac un arc (i,j) cu
nrdf(i)>nrdf(j) este de ntoarcere sau de traversare astfel:
ki;
while k0 & kj
ktata(k)
if k=0 then write(traversare)
else write(ntoarcere)

3.6.

Parcurgerea BF a grafurilor neorientate

Fie un graf G=(V,M) i fie i0 un vrf al su. n unele situaii se pune


probleme determinrii vrfului j cel mai apropiat de i0 cu o anumit proprietate.
Parcurgerea DF nu mai este adecvat.
Parcurgerea pe lime BF (Breadth First) urmrete vizitarea vrfurilor n
ordinea cresctoare a distanelor lor fa de i0. Este generalizat parcurgerea pe

42

3. GRAFURI

niveluri a arborilor, inndu-se cont c graful poate conine cicluri. Va fi deci


folosit o coad C.
La fel ca i la parcurgerea DF, vrfurile vizitate vor fi marcate.
Pentru exemplul din primul paragraf al acestui capitol, parcurgerea BF
produce vrfurile n urmtoarea ordine:
1, 4, 2, 3, 5, 6, 8, 9, 7.
Algoritmul urmtor realizeaz parcurgea pe lime a componentei conexe
a lui i0:
for i=1,n
vizitat(i) false
C ; C i0; vizitat(i0) true
while C
i C; vizit(i)
if not vizitat(j)
then j C; vizitat(j)true
for toi j vecini ai lui i

La fel ca pentru parcurgerea DF, algoritmul poate fi completat pentru


parcurgerea ntregului graf, pentru determinarea unei pduri n care fiecare arbore
este un arbore parial al unei componente conexe etc.

4
4.1.

METODA GREEDY

Descrierea metodei Greedy

Metoda Greedy (greedy=lacom) este aplicabil problemelor de optim.


Considerm mulimea finit A={a1,...,an} i o proprietate p definit pe
mulimea submulimilor lui A:
p() = 1
p:P(A){0,1} cu
p(X) = 1 p(Y) = 1, Y X
O submulime SA se numete soluie dac p(S)=1.

Dintre soluii va fi aleas una care optimizeaz o funcie de cost


f:P(A)R dat.
Metoda urmrete evitarea parcurgerii tuturor submulimilor (ceea ce ar
necesita un timp de calcul exponenial), mergndu-se "direct" spre soluia optim.
Nu este ns garantat obinerea unei soluii optime; de aceea aplicarea metodei
Greedy trebuie nsoit neaprat de o demonstraie.
Distingem dou variante generale de aplicare a metodei Greedy:
S
for i=1,n
x alege(A); AA\{x}
if p(S{x})=1
then SS{x}

prel(A)
S
for i=1,n
if p(S{ai})=1
then SS{ai}

Prima variant alege n mod repetat cte un element oarecare al mulimii A


i l adaug soluiei curente S numai dac n acest mod se obine tot o soluie. n a
doua variant procedura prel realizeaz o permutare a elementelor lui A, dup
care elementele lui A sunt analizate n ordine i adugate soluiei curente S numai
dac n acest mod se obine tot o soluie.

Observaii:
n algoritmi nu apare funcia f !!
timpul de calcul este liniar (exceptnd prelucrrile efectuate de procedura
prel i funcia alege);

4. METODA GREEDY

44

dificultatea const n a concepe funcia alege, respectiv procedura prel,


n care este "ascuns" funcia f.

Exemplul 1. Se consider mulimea de valori reale A={a1,...,an}. Se


caut submulimea a crei sum a elementelor este maxim.
Vom parcurge mulimea i vom selecta numai elementele pozitive, care
vor fi plasate n vectorul soluie s.
k0
for i=1,n
if ai>0
then kk+1; skai
write(s)

Exemplul 2. Se cere cel mai lung ir strict cresctor cu elemente din


vectorul a=(a1,...,an).
ncepem prin a ordona cresctor elementele vectorului a (corespunztor
procedurii prel). Apoi parcurgem vectorul de la stnga la dreapta. Folosim
notaiile:
lung = lungimea celui mai lung ir strict cresctor;
k = lungimea irului strict cresctor curent;
baza = poziia din a de pe care ncepe irul strict cresctor curent.
k1; s1a1; lung1; baza1
for i=2,n
if ai>sk then kk+1; sk ai
else if k>lung then lungk; bazai-k
k1; s1ai

De exemplu, dac n urma ordonrii vectorul a este:


a=(1,1,2,3,4,4,5,6,7,8,8), vom obine succesiv:
baza=1; lung=1; s=(1)
baza=2; lung=4; s=(1,2,3,4)
baza=6; lung=5; s=(4,5,6,7,8).

(Contra)exemplul 3. Fie mulimea A={a1,...,an} cu elemente pozitive.


Caut submulimea de sum maxim, dar cel mult egal cu M dat.
Dac procedm ca n Exemplul 1, pentru A=(6,3,4,2) i M=7 obinem
{6}. Dar soluia optim este {3,4} cu suma egal cu 7.
Continum cu prezentarea unor exemple clasice.

4.2. Memorarea textelor pe band

4.2.

45

Memorarea textelor pe band

Textele cu lungimile L(1),...,L(n) urmeaz a fi aezate pe o band.


Pentru a citi textul de pe poziia k, trebuie citite textele de pe poziiile
1,2,...,k (conform specificului accesului secvenial pe band).
O soluie nseamn o permutare pSn.
Pentru o astfel de permutare (ordine de aezare a textelor pe band), timpul
necesar pentru a citi textul de pe poziia k este: Tp(k)=L(p1)+...+L(pk).
Presupunnd textele egal probabile, problema const n determinarea unei
permutri p care minimizeaz funcia de cost:
T(p)=

1 n
Tp(k).
n k=1

S observm c funcia T se mai poate scrie: T(p)=

1 n
(n k + 1)L(pk )
n k=1

(textul de pe poziia k este citit dac vrem s citim unul dintre textele de pe
poziiile k,...,n).
Conform strategiei Greedy, ncepem prin a ordona cresctor vectorul L.
Rezult c n continuare L(i)<L(j), i<j.
Demonstrm c n acest mod am obinut modalitatea optim, adic
permutarea identic minimizeaz funcia de cost T.
Fie pSn optim, adic p minimizeaz funcia T. Dac p este diferit de
permutarea identic, atunci i<j cu L(pi)>L(pj):
p=(

pi

pj

Considerm permutarea p' n care am interschimbat elementele de pe poziiile i


i j:
p'=(

pj

pi

Atunci n[T(p)-T(p)] = (n-i+1)L(pi) + (n-j+1)L(pj) - (n-i+1)L(pj) - (n-j+1)L(pi) =


= (j-i)L(pi)+(i-j)L(pj) =
= (j-i)[L(pi)-L(pj)]>0

ambii factori fiind pozitivi.


Rezult c T(p)<T(p). Contradicie.

4. METODA GREEDY

46

4.3.

Problema continu a rucsacului

Se consider un rucsac de capacitate (greutate) maxim G i n obiecte


caracterizate prin:
- greutile lor g1,...,gn;
- ctigurile c1,...,cn obinute la ncrcarea lor n totalitate n rucsac.
Din fiecare obiect poate fi ncrcat orice fraciune a sa.
Se cere o modalitate de ncrcare de (fraciuni de) obiecte n rucsac, astfel
nct ctigul total s fie maxim.
xi [0,1], i
n
gi xi G
i
=1

Prin soluie nelegem un vector x=(x1,...,xn) cu

O soluie optim este o soluie care maximizeaz funcia f(x)= cixi .


i=1

Dac suma greutilor obiectelor este mai mic dect G, atunci vom ncrca
toate obiectele: x=(1,...,1). De aceea presupunem n continuare c
g1+...+gn>G.
Conform strategiei Greedy, ordonm obiectele descresctor dup ctigul
la unitatea de greutate, deci lucrm n ipoteza:
c
c1 c2

... n
gn
g1 g 2

(*)

Algoritmul const n ncrcarea n aceast ordine a obiectelor, atta timp


ct nu se depete greutatea G (ultimul obiect pote fi eventual ncrcat parial):
G1 G { G1 reprezint greutatea disponibil }
for i=1,n
if giG1 then xi1; G1G1-gi
else xiG1/gi;
for j=i+1,n
xj 0
stop
write(x)

Am obinut deci x=(1,...,1,xj,0,...,0) cu xj[0,1).


Artm c soluia astfel obinut este optim.

4.3. Problema continu a rucsacului

47

n
giy i = G
Fie y soluia optim: y=(y1,...,yk,...,yn) cu i=1
n
c y maxim
i=1 i i
Dac yx, fie k prima poziie pe care ykxk.

Observaii:
 kj: pentru k>j se depete G.
 yk<xk:
pentru k<j: evident, deoarece xk=1;
pentru k=j: dac yk>xk se depete G.
Considerm soluia: y=(y1,...,yk-1,xk,yk+1,...,yn) cu <1
(primele k-1 componente coincid cu cele din x). Pstrm greutatea total G, deci:
gkxk+(gk+1yk+1+...+gnyn)=gkyk+gk+1yk+1+...+gnyn. Rezult:
gk(xk-yk)=(1-)(gk+1yk+1+...+gnyn)
(**)
Comparm performana lui y' cu cea a lui y:
f(y)-f(y) = ckxk +ck+1yk+1 +...+ cnyn - (ckyk+ck+1yk+1 +...+cnyn) =
= ck(xk-yk) + (-1)(ck+1yk+1+...+cnyn) =
= ck/gk[gk(xk-yk)+(-1)(gk/ckck+1yk+1+...+gk/ckcnyn)]
Dar -1>0 i gk/ck gs/cs, s>k, conform (*). Atunci:
f(y)-f(y)>ck/gk [gk(xk-yk)+(-1)(gk+1yk+1+...+gnyn)]=0
conform (**), deci f(y')>f(y). Contradicie.

Problema discret a rucsacului difer de cea continu prin faptul c


fiecare obiect poate fi ncrcat numai n ntregime n rucsac.
S observm c aplicarea metodei Greedy eueaz n acest caz. ntradevr, aplicarea ei pentru:
G=5, n=3 i g=(4,3,2), c=(6,4,2.5)
are ca rezultat ncrcarea primul obiect; ctigul obinut este 6. Dar ncrcarea
ultimelor dou obiecte conduce la ctigul superior 6.5.

4.4.

Problema arborelui parial de cost minim

Fie G=(V,M) un graf neorientat cu muchiile etichetate cu costuri strict


pozitive. Se cere determinarea unui graf parial de cost minim.

4. METODA GREEDY

48

Ca exemplificare, s considerm n orae iniial nelegate ntre ele. Pentru


fiecare dou orae se cunoate costul conectrii lor directe (considerm acest cost
egal cu + dac nu este posibil conectarea lor). Constructorul trebuie s
conecteze oraele astfel nct din oricare ora s se poat ajunge n oricare altul.
Ce legturi directe trebuie s aleag constructorul astfel nct costul total al
lucrrii s fie minim?
Este evident c graful parial cutat este un arbore (dac ar exista un ciclu,
am putea ndeprta orice muchie din el, cu pstrarea conexitii i micorarea
costului total).
Vom aplica metoda Greedy: adugm mereu o muchie de cost minim
dintre cele nealese i care nu formeaz un ciclu cu precedentele muchii alese.
Acest algoritm poart numele de algoritmul lui Kruskal.
Ca de obicei, fie |V|=n i |M|=m. Vor fi alese deci n-1 muchii.
Construim o matrice mat cu m linii i trei coloane. Pe fiecare linie apar
extremitile i i j ale unei muchii, precum i costul acestei muchii.
ncepem prin a ordona liniile matricii cresctor dup ultima coloan (a
costurilor muchiilor).
Exemplu. Considerm graful de mai jos i matricea mat ataat.
2

2
5

5
2

3
4
4

1
1
4
1
3
2
2

2
4
5
5
4
5
3

2
2
2
3
4
5
5

Conform algoritmului lui Kruskal, vor fi alese n ordine muchiile:


(1,2), (1,4), (4,5), (3,4)
cu costul total egal cu 10. Muchia (1,5) nu a fost aleas deoarece formeaz cu
precedentele un ciclu.
Dificultatea principal const n verificarea faptului c o muchie formeaz
sau nu un ciclu cu precedentele. Plecnd de la observaia c orice soluie parial
este o pdure, vom asocia fiecrui vrf i un reprezentant ri care identific
componenta conex (arborele) din care face parte vrful n soluia parial.
Atunci:

4.4. Problema arborelui parial de cost minim

49

o muchie (i,j) va forma un ciclu cu precedentele ri=rj;


la alegerea (adugarea) unei muchii (i,j) vom pune rkrj pentru orice
vrf k cu rk=ri (unim doi arbori, deci toate vrfurile noului arbore trebuie
s aib acelai reprezentant).

n algoritmul care urmeaz metoda descris, l este numrul liniei curente


din matricea mat, nm este numrul de muchii alese, iar cost este costul muchiilor
alese.
ri i, i=1,n
l 1; nm 0; cost 0
while lm & nm<n-1
i1 mat(l,1); i2 mat(l,2)
r1 ri1; r2 ri2
if r1r2
then nm nm+1; cost cost+mat(l,3);
write(i1,i2)
for k=1,n
if rk=r2 then rk r1
l l+1
if nm<n-1 then write('Graf neconex')
else write('Graf conex. Costul=,cost)

Demonstrm n continuare corectitudinea algoritmului lui Kruskal.


Fie G=(V,M) un graf conex.
PM se numete mulime promitoare de muchii dac poate fi extins la
un arbore parial P de cost minim. n particular P nu conine cicluri (este o
pdure).
Propoziie. La fiecare pas din algoritmul lui Kruskal muchiile alese
formeaz o mulime promitoare P. n plus, muchiile din P\P nu au costuri mai
mici dect cele din P.
Fie P mulimea promitoare a muchiilor selectate la primii k pai i fie m
muchia considerat la pasul k+1. Deosebim situaiile:
1) dac m nchide un ciclu n P, ea este ignorat. P i P rmn aceleai.
2) dac m nu nchide un ciclu n P i face parte din P, noile instane ale lui P i
P sunt P{m} i P.
3) dac m nu nchide un ciclu n P i nu face parte din P, atunci P{m} are un
ciclu. n el exist, n afar de m, o muchie m' din P\P, deci de cost mai

4. METODA GREEDY

50

mare sau egal dect cel al lui m. Fie P'=P {m}\{m}. P' este tot un
arbore parial de cost minim. Noile instane ale lui P i P sunt P{m} i
P'.

n final, o mulime promitoare cu n-1 muchii este chiar un arbore parial


de cost minim.
Observaie. Tot o ilustrare a metodei Greedy pentru problema enunat
este algoritmul lui Prim, care const n urmtoarele:
- se ncepe prin selectarea unui vrf;
- la fiecare pas alegem o muchie (i,j) de lungime minim cu i selectat,
dar j neselectat.
De aceast dat, la fiecare pas se obine un arbore. Propunem ca exerciiu
demonstrarea faptului c dup n-1 pai se obine un arbore parial de cost minim.

METODA BACKTRACKING

Aa cum s-a subliniat n capitolele anterioare, complexitatea n timp a


algoritmilor joac un rol esenial. n primul rnd un algoritm este considerat
"acceptabil" numai dac timpul su de executare este polinomial, adic de ordinul
O(nk) pentru un anumit k; n reprezint numrul datelor de intrare.
Pentru a ne convinge de acest lucru, vom considera un calculator capabil
s efectueze un milion de operaii pe secund. n tabelul urmtor apar timpii
necesari pentru a efectua n3, 2n i 3n operaii, pentru diferite valori mici ale lui n:
3

n
2n
3n

n=20

n=40

n=60

1 sec
58 min

12,7 zile
3855 secole

0,2 sec
366 secole
1013 secole

Chiar dac n prezent calculatoarele performante sunt capabile s efectueze


zeci de miliarde de operaii pe secund, tabelul de mai sus arat c algoritmii
exponeniali nu sunt acceptabili.

5.1.

Descrierea metodei Backtracking

Fie produsul cartezian X=X1 ... Xn. Cutm xX cu (x)=1, unde


:X {0,1} este o proprietate definit pe X.
Din cele de mai sus rezult c generarea tuturor elementelor produsului
cartezian X nu este acceptabil.
Metoda backtracking ncearc micorarea timpului de calcul. X este numit
spaiul soluiilor posibile, iar sintetizeaz condiiile interne.
Vectorul x este construit progresiv, ncepnd cu prima component. Nu se
trece la atribuirea unei valori lui xk dect dac am stabilit valori pentru
x1,...,xk-1 i k-1(x1,...,xk-1)=1. Funciile k:X1...Xk {0,1} se
numesc condiii de continuare i sunt de obicei restriciile lui la primele k
variabile. Condiiile de continuare sunt strict necesare, ideal fiind s fie i
suficiente.
Distingem urmtoarele cazuri posibile la alegerea lui xk:

5. METODA BACKTRACKING

52

1)
2)

3)
4)

Atribuie i avanseaz: mai sunt valori neconsumate (neanalizate) din


Xk i valoarea xk aleas satisface k se mrete k.
ncercare euat: mai sunt valori neconsumate din Xk i valoarea xk
aleas dintre acestea nu satisface k se va relua, ncercndu-se
alegerea unei noi valori pentru xk.
"Revenire": nu mai exist valori neconsumate din Xk (Xk epuizat)
ntreaga Xk devine disponibil i kk-1.
"Revenire dup determinarea unei soluii": este reinut soluia.

Reinerea unei soluii const n apelarea unei proceduri retsol care


prelucreaz soluia (o tiprete, o compar cu alte soluii etc.) i fie oprete
procesul (dac se dorete o singur soluie), fie prevede kk-1 (dac dorim s
determinm toate soluiile).
Notm prin CkXk mulimea valorilor consumate din Xk. Algoritmul este
urmtorul:
Ci, i;
k1;
while k>0
if k=n+1
then retsol(x); kk-1; { revenire dup obinerea unei soluii }
else if CkXk
then alege vXk\Ck; CkCk{v};
if k(x1,...,xk-1,v)=1
then xkv; kk+1;
{ atribuie i avanseaz }
else
{ ncercare euat }
else Ck; kk-1;
{ revenire }

Pentru cazul particular X1=...=Xn={1,...,s}, algoritmul se simplific


astfel:
k1; xi0, i=1,...,n
while k>0
if k=n+1
then retsol(x); kk-1;
{ revenire dup obinerea unei soluii }
else if xk<s
then xkxk+1;
if k(x1,...,xk)=1
{ atribuie i avanseaz }
then kk+1;
else
{ ncercare euat }
else xk0; kk-1;
{ revenire }

5.2. Exemple

5.2.

53

Exemple

n exemplele care urmeaz, k va fi notat n continuare prin cont(k). Se


aplic algoritmul de mai sus pentru diferite forme ale funciei de continuare.
1) Colorarea hrilor. Se consider o hart. Se cere colorarea ei folosind cel
mult n culori, astfel nct oricare dou ri vecine (cu frontier comun de
lungime strict pozitiv) s fie colorate diferit.
Fie xk culoarea curent cu care este colorat ara k.
function cont(k: integer): boolean;
b true; i 1;
while b and (i<k)
if vecin(i,k) & xi=xk
then b false
else i i+1
cont b
end;

unde vecin(i,k) este true dac i numai dac rile i i k sunt vecine.
2) Problema celor n dame
Se consider un caroiaj de dimensiuni nn. Prin analogie cu o tabl de ah
(n=8), se dorete plasarea a n dame pe ptrelele caroiajului, astfel nct s nu
existe dou dame una n btaia celeilalte (adic s nu existe dou dame pe aceeai
linie, coloan sau diagonal).
Evident, pe fiecare linie vom plasa exact o dam. Fie xk coloana pe care
este plasat dama de pe linia k.
Damele de pe liniile i i k sunt:
- pe aceeai coloan: dac xi=xk ;
- pe aceeai diagonal: dac |xi-xk|=k-i.
function cont(k:integer): boolean;
b true; i 1;
while b and i<k
if |xi-xk|=k-i or xi=xk
then b false
else i i+1;
cont b
end;

5. METODA BACKTRACKING

54

3) Problema ciclului hamiltonian


Se consider un graf neorientat. Un ciclu hamiltonian este un ciclu care
trece exact o dat prin fiecare vrf al grafului.
Pentru orice ciclu hamiltonian putem presupune c el pleac din vrful 1.
Vom nota prin xi al i-lea vrf din ciclu.
Un vector x=(x1,...,xn) este soluie dac:
1) x1=1 i
2) {x2,...,xn}={2,...,n} i
3) xi,xi+1 vecine, i=1,...,n-1 i
4) xn,x1 vecine.
Vom considera c graful este dat prin matricea sa de adiacen.
function cont(k:integer):boolean;
if a(xk-1,xk)=0
then cont false
else i 1; b true;
while b & (i<k)
if xk=xi then b false
else i i+1
if k=n then b b a(xn,x1)=1
cont b
end

5.3.

Esena metodei Backtracking


Metoda backtracking poate fi descris astfel:
Backtracking = parcurgerea limitat *) n adncime a unui arbore
*)

conform condiiilor de continuare

Rolul condiiilor de continuare este ilustrat n figura ce urmeaz. Dac


pentru xk este aleas o valoare ce nu satisface condiiile de continuare, atunci la
parcurgerea n adncime este evitat parcurgerea unui ntreg subarbore.

5.3. Esena metodei Backtracking

55

x1

x2

xk

5.4.

Variante

Variantele cele mai uzuale ntlnite n aplicarea metodei backtracking sunt


urmtoarele:
- soluiile pot avea un numr variabil de componente
i/sau
- dintre soluii alegem una care optimizeaz o funcie dat.
Exemplu. Fie irul a=(a1,...,an)Zn. Cutm un subir strict cresctor
de lungime maxim.
Cutm deci indicii x1,...,xk care satisfac condiiile:
1) 1x1<...<xkn
2) ax1 < ax2 < . . . < axk
3) k maxim.
Pentru n=8 i a=(1,4,2,3,7,5,8,6) va rezulta k=5.
n aceast problem vom nelege prin soluie posibil o soluie care nu
poate fi continuat, ca de exemplu (4,7,8).

5. METODA BACKTRACKING

56

Fie xf i kf soluia optim curent i lungimea sa. Procedm astfel:


 Completm la capetele irului cu - i + :
a0 -; nn+1; an +;
 Funcia cont are urmtoarea form:
function cont(k)
cont a xk - 1 < a xk
end;
 Procedura retsol are forma:
procedure retsol(k)
if k>kf then xfx; kfk;
end;

Algoritmul backtracking se modific astfel:

k1; x00; x10; kf0;


while k>0
if xk<n
then xkxk+1;
if cont(k)
{ an=+ }
then if xk=n
then retsol(k); kk-1
else kk+1; xkxk-1
else
else kk-1;

Observaie. Se face tot o parcurgere limitat n adncime a unui arbore.

5.5.

Abordarea recursiv
Descriem abordarea recursiv pentru X1=...=Xn={1,...,s}.
Apelul iniial este: back(1).

procedure back(k)
if k=n+1
then retsol
else for i=1,s
xki;
if cont(k) then back(k+1);

revenirea din recursivitate


end

5.5. Abordarea recursiv

57

Exemplu. Dorim s producem toate irurile de n paranteze ce se nchid


corect.
Este evident c problema are soluii dac i numai dac n este par.
Fie nr( = numrul de paranteze deschise pn la poziia curent i nr) =
numrul de paranteze deschise pn la poziia curent. Fie dif = nr(-nr).
Atunci trebuie ndeplinite condiiile:
dif0 pentru k<n;
dif=0 pentru k=n.
Pornirea algoritmului backtracking se face prin:
a1( ; dif1; back(2);
Procedura back are urmtoarea form:
procedure back(k)
if k=n+1
then retsol
{scrie soluia}
else ak( ; dif++;
if dif n-k then back(k+1)
dif--;
ak); dif--;
if dif0 then back(k+1)
dif++;
end.

Observaie. n exemplul tratat backtracking-ul este optimal, deoarece se


avanseaz dac i numai dac exist anse de obinere a unei soluii. Cu alte
cuvinte, condiiile de continuare nu sunt numai necesare, dar i suficiente.

5.6.

Metoda backtracking n plan

Se consider un caroiaj (matrice) A cu m linii i n coloane. Poziiile pot fi:


libere: aij=0;
ocupate: aij=1.
Se mai d o poziie (i0,j0). Se caut toate drumurile care ies n afara
matricii, trecnd numai prin poziii libere.
-

Variante:
cum putem ajunge ntr-o poziie (i1,j1) dat?
se cere determinarea componentelor conexe.

5. METODA BACKTRACKING

58

Procedm astfel:


Micrile posibile sunt date printr-o matrice depl cu dou linii i


ndepl coloane. De exemplu, dac deplasrile permise sunt cele ctre
poziiile vecine situate la Est, Nord, Vest i Sud, matricea are forma:
1 0 1 0

depl =
0 1 0 1





Bordm matricea cu 2 pentru a nu studia separat ieirea din matrice; n


acest mod s-au introdus linia 0 i linia m+1, precum i coloanele 0 i
n+1.
Pentru refacerea drumurilor, pentru fiecare poziie atins memorm
legtura la poziia precedent.
Dac poziia e liber i putem continua, punem aij=-1 (a fost atins),
continum i apoi repunem aij0 (ntoarcerea din recursivitate).

Programul n Java are urmtoarea form (reamintim c prezentarea clasei


IO.java este fcut n anex):
class elem {
int i,j; elem prec;
static int m,n,i0,j0,ndepl;
static int[][] mat;
static int[][] depl = { {1,0,-1,0}, {0,-1,0,1} };
static { ndepl = depl[0].length; }
elem() {
int i,j;
IO.write("m,n = "); m = (int) IO.read();
n = (int) IO.read();
//m+2,n+2
mat = new int[m][n];
for(i=1; i<m-1; i++)
for(j=1; j<n-1; j++) mat[i][j] = (int) IO.read();
for (i=0;i<n;i++) {mat[0][i] = 2; mat[m-1][i] = 2;}
for (j=0;j<m;j++) {mat[j][0] = 2; mat[j][n-1] = 2;}
IO.write("i0,j0 = "); i0 = (int) IO.read();
j0 = (int) IO.read();
}
elem(int ii,int jj,elem x) { i=ii; j=jj; prec=x; }
String print(elem x) {
if (x == null) return "(" + i + "," + j + ")";
else return x.print(x.prec)+" "+"("+i+","+j+")";
}

5.6. Metoda backtracking n plan

59

void p() {
elem x; int ii,jj;
for (int k=0; k<ndepl; k++) {
ii = i+depl[0][k]; jj = j+depl[1][k];
if (mat[ii][jj] == 1);
else if (mat[ii][jj]==2) IO.writeln(print(prec));
else if (mat[ii][jj]==0) {
mat[i][j] = -1; x = new elem(ii,jj,this);
x.p(); mat[i][j] = 0;
}
}
}
}
class DrumPlan {
public static void main(String[] args) {
new elem();
elem start = new elem(elem.i0,elem.j0,null);
start.p();
}
}

METODA DIVIDE ET IMPERA

Metoda Divide et Impera ("desparte i stpnete") const n mprirea


repetat a unei probleme de dimensiuni mari n mai multe subprobleme de acelai
tip, urmat de rezolvarea acestora i combinarea rezultatelor obinute pentru a
determina rezultatul corespunztor problemei iniiale. Pentru fiecare subproblem
procedm n acelai mod, cu excepia cazului n care dimensiunea ei este suficient
de mic pentru a fi rezolvat direct.
Este evident caracterul recursiv al acestei metode.

6.1.

Schema general

Descriem schema general pentru cazul n care aplicm metoda pentru o


prelucrare oarecare asupra elementelor unui vector. Funcia DivImp, care ntoarce
rezultatul prelucrrii asupra unei subsecvene ap,...,au, va fi apelat prin
DivImp(1,n).
function DivImp(p,u)
if up<
then r Prel(p,u)
else m Interm (p,u);
r1 DivImp(p,m);
r2 DivImp(m+1,u);
r Combin(r1,r2)
return r
end;

unde:
- funcia Interm ntoarce un indice n intervalul p..u; de obicei m=(p+u)/2 ;
- funcia Prel este capabil s ntoarc rezultatul subsecvenei p..u, dac
aceasta este suficient de mic;
- funcia Combin ntoarce rezultatul asamblrii rezultatelor pariale r1 i r2.

6.1. Schema general

61

Exemple:



Maximul elementelor unui vector poate fi evident calculat folosind metoda


Divide et Impera;
Parcurgerile n preordine, inordine i postordine ale unui arbore binar, precum
i sortarea folosind arbori de sortare, urmeaz ntocmai aceast metod.

6.2.

Cutarea binar

Se consider vectorul a=(a1, ...,an) ordonat cresctor i o valoare x.


Se cere s se determine dac x apare printre componentele vectorului.
Problema enunat constituie un exemplu pentru cazul n care problema se
reduce la o singur subproblem, deci dispare pasul de recombinare a rezultatelor
subproblemelor.
innd cont de faptul c a este ordonat cresctor, vom compara pe x cu
elementul din "mijlocul" vectorului. Dac avem egalitate, algoritmul se ncheie; n
caz contrar vom lucra fie pe "jumtatea" din stnga, fie pe cea din dreapta.



Vom aduga a 0 =-, an+1=+ . Cutm perechea (b,i) dat de:


(true,i)
dac ai=x;
(false,i)
dac ai-1<x<ai.

Deoarece problema se reduce la o singur subproblem, nu mai este


necesar s folosim recursivitatea.
Algoritmul este urmtorul:
procedure CautBin
p 1; u n
while pu
i (p+u)/2
case ai>x : u i-1
ai=x : write(true,i); stop
ai<x : p i+1
write(false,p)
end

Algoritmul necesit o mic analiz, legat de corectitudinea sa parial.


Mai precis, ne ntrebm: cnd se ajunge la p>u?
 pentru cel puin 3 elemente : nu se poate ajunge la p>u;

6. METODA DIVIDE ET IMPERA

62




pentru 2 elemente, adic pentru u=p+1: se alege i=p. Dac x<ai, atunci
up-1. Se observ c se iese din ciclul while i ai-1<x<ai=ap;
pentru un element, adic p=u: se alege i=p=u. Dac x<ai atunci up-1, iar
dac x>ai atunci pu+1; n ambele cazuri se prsete ciclul while i se
tiprete un rezultat corect.

6.3.

Problema turnurilor din Hanoi

Se consider 3 tije. Iniial, pe tija 1 se afl n discuri cu diametrele


decresctoare privind de la baz ctre vrf, iar pe tijele 2 i 3 nu se afl nici un
disc. Se cere s se mute aceste discuri pe tija 2, ajutndu-ne i de tija 3. Trebuie
respectat condiia ca n permanen, pe orice tij, sub orice disc s se afle baza
tijei sau un disc de diametru mai mare.
O mutare este notat prin (i,j) i semnific deplasarea discului din
vrful tijei i deasupra discurilor aflate pe tija j. Se presupune c mutarea este
corect (vezi condiia de mai sus).
Fie H(m;i,j) irul de mutri prin care cele m discuri din vrful tijei i
sunt mutate peste cele de pe tija j, folosind i a treia tij, al crei numr este
evident 6-i-j. Problema const n a determina H(n;1,2).
Se observ c este satisfcut relaia:
H(m;i,j)= H(m-1;i,6-i-j) (i,j)

H(m-1;6-i-j,j)
(*)
cu respectarea condiiei din enun. Deci problema pentru m discuri a fost redus la
dou probleme pentru m-1 discuri, al cror rezultat este asamblat conform (*).
Corespunztor, vom executa apelul Hanoi(n,1,2), unde procedura
Hanoi are forma:
procedure Hanoi(n,i,j)
if n=1
then write(i,j)
else k6-i-j;
Hanoi(n-1,i,k); Hanoi(1,i,j); Hanoi(n-1,k,j)
end

Observaie. Numrul de mutri este 2n-1.

6.4.

Sortarea prin interclasare


Fie a=(a1,...,an) vectorul care trebuie ordonat cresctor.

6.4. Sortarea prin interclasare

63

Ideea este urmtoarea: mprim vectorul n doi subvectori, ordonm


cresctor fiecare subvector i asamblm rezultatele prin interclasare. Se aplic
deci ntocmai metoda Divide et Impera.
ncepem cu procedura de interclasare. Fie secvena de indici p..u i fie m
un indice intermediar. Presupunnd c (ap,...,am) i (am+1,...,au) sunt
ordonai cresctor, procedura Inter va ordona cresctor ntreaga secven
(ap,...,au).
Mai precis, vom folosi notaiile:
k1 = indicele curent din prima secven;
k2 = indicele curent din a doua secven;
k3 = poziia pe care va fi plasat cel mai mic dintre ak1 i ak2 n vectorul auxiliar b.
procedure Inter(p,m,u)
k1p; k2m+1; k3p;
while k1m & k2u
if ak1<ak2 then bk3ak1; k1k1+1
else bk3ak2; k2k2+1
k3k3+1
{ au fost epuizate elementele primei subsecvene }
if k1>m
then for i=k2,u
bk3ai; k3k3+1
else for i=k1,m
bk3ai; k3k3+1
for i=p,u
aibi
end
Timpul de calcul este de ordinul O(u-p), adic liniar n lungimea

secvenei analizate.
Programul principal urmeaz ntocmai strategia Divide et Impera, deci se
face apelul SortInter(1,n), unde procedura recursiv SortInter are forma:
procedure SortInter(p,u)
if p=u
then
else m (p+u)/2;
SortInter(p,m); SortInter(m+1,u);
Inter(p,m,u)
end

64

6. METODA DIVIDE ET IMPERA

Calculm n continuare timpul de executare T(n), unde T(n) se poate


scrie:
t0 (constant), pentru n=1;
2T(n/2)+an, pentru n>1, unde a este o constant: problema de dimensiune n
s-a descompus n dou subprobleme de dimensiune n/2, iar combinarea
rezultatelor s-a fcut n timp liniar (prin interclasare).
Presupunem c n=2k. Atunci:
T(n) = T(2k) =2 T(2k-1) + a 2k =
=2[2T(2k-2) + a 2k-1] + a 2k = 22T(2k-2) + 2 a 2k =
=22[T(2k-3) + a 2k-2] + 2 a 2k = 2 3 T(2k-3) + 3 a 2k =
. . .
= 2iT(2k-i) + i. a. 2k =
. . .
=2kT(0) + k a 2k = nt0 + a.n.log 2 n.

Rezult c T(n)=0(n.log n).


Se observ c s-a obinut acelai timp ca i pentru sortarea cu ansamble.
Meniune. Se poate demonstra c acest timp este optim.

6.5.

Metoda Quicksort

Prezentm nc o metod de sortare a unui vector a=(a1,...,an). Va fi


aplicat tot metoda Divide et Impera. i de aceast dat fiecare problem va fi
descompus n dou subprobleme mai mici de aceeai natur, dar nu va mai fi
necesar combinarea (asamblarea) rezultatelor rezolvrii subproblemelor.
Fie (ap,...,au) secvena curent care trebuie sortat. Vom poziiona pe
ap n secvena (ap,...,au), adic printr-o permutare a elementelor secvenei
x=ap va trece pe o poziie k astfel nct:
 toate elementele aflate la stnga poziiei k vor fi mai mici dect x;
 toate elementele aflate la dreapta poziiei k vor fi mai mari dect x.
n acest mod ap va aprea pe poziia sa final, rmnnd apoi s ordonm
cresctor elementele aflate la stnga sa, precum i pe cele aflate la dreapta sa.
Fie poz funcia cu parametrii p i u care ntoarce indicele k pe care va fi
poziionat ap n cadrul secvenei (ap,...,au).
Atunci sortarea se realizeaz prin apelul QuickSort(1,n), unde
procedura QuickSort are forma:

6.5. Metoda Quicksort

65

procedure QuickSort(p,u)
if pu
then
else k poz(p,u); QuickSort(p,k-1); QuickSort(k+1,u)
end

Funcia poz lucreaz astfel:


function poz(p,u)
ip; ju; ii0; jj-1
while i<j
if ai<aj
then
else ai aj; (ii,jj) (-ii,-jj)
ii+ii; jj+jj
(*)
poz i
end

S urmrim cum decurg calculele pentru secvena:


(a4,...,a11)=(6,3,2,5,8,1,9,7)
 se compar 6 cu a11,a10,... pn cnd gsim un element mai mic. Acesta
este a9=1. Se interschimb 6 cu 1. Acum secvena este (1,3,2,5,8,6,9,7)
i vom lucra n continuare pe subsecvena (3,2,5,8,6), schimbnd direcia
de comparare conform (*);
 6 va fi comparat succesiv cu 3,2,... pn cnd gsim un element mai
mare. Acesta este a8=8. Se interschimb 6 cu 8.
Se obine astfel (1,3,2,5,6,8,9,7), n care la stnga lui 6 apar valori
mai mici, iar la dreapta lui 6 apar valori mai mari, deci l-am poziionat pe 6 pe
poziia 8, valoare ntoars de funcia poz.

Observaie. Cazul cel mai defavorabil pentru metoda Quicksort este cel n
care vectorul este deja ordonat cresctor: se compar a1 cu a2,...,an rezultnd
c el se afl pe poziia final, apoi se compar a2 cu a3,...,an rezultnd c el se
afl pe poziia final etc. Timpul n acest caz este de ordinul O(n2).
Trecem la calculul timpului mediu de executare al algoritmului Quicksort.
Vom numra cte comparri se efectueaz (componentele vectorului nu sunt
neaprat numere, ci elemente dintr-o mulime ordonat oarecare). Timpul mediu
este dat de formulele:
1 n

[T(k 1) + T(n k)]


T(n) = n 1 +
n k =1

T(1) = T(0) = 0

6. METODA DIVIDE ET IMPERA

66

deoarece:
 n cazul cel mai defavorabil a1 se compar cu celelalte n-1 elemente;
 a1 poate fi poziionat pe oricare dintre poziiile k=1,2,...,n; considerm
aceste cazuri echiprobabile;
 T(k-1) este timpul (numrul de comparri) necesar ordonrii elementelor
aflate la stnga poziiei k, iar T(n-k) este timpul necesar ordonrii
elementelor aflate la dreapta poziiei k.
nT(n) = n(n-1)+2[T(0)+T(1)+...+T(n-1)]
(n-1)T(n-1) = (n-1)(n-2)+2[T(0)+...+T(n-2)]

Scznd cele dou relaii obinem:


nT(n)(n-1)T(n-1) = 2(n-1)+ 2T(n-1), deci:
nT(n) = (n+1)T(n-1)+2(n-1).

mprim cu n(n+1):
T(n)
T(n 1) 2(n 1)
=
+
n + 1
n
n(n + 1)
1
T(n)
T(n 1)
2
=
+ 2

n
n + 1
T(n)
n + 1
1
T(n 1)
T(n 2)
2
+ 2
=

n 1
n
T(n 1)
n
...........................

f(x)=ln x

1
T(2)
T(1)
2
=
+ 2
3
2
2
3

2 3

n+1

Prin adunarea relaiilor de mai sus, obinem:


1
2
1
T(n)
1
= 2
+
+ ... + +
1
3
n + 1
n
n + 1
n + 1

Cum suma ultimilor doi termeni este negativ, rezult:


T(n)
2
n +1

n +1

1
dx = 2lnx|2n+1 2 ln(n+1)
x

(am folosit o inegalitate bazat pe sumele Rieman pentru funcia f(x)=ln x).
Deci T(n)=0(n.log n).
ncheiem cu meniunea c metoda Divide et Impera are o larg
aplicativitate i n calculul paralel.

METODA PROGRAMRII DINAMICE

Vom ncepe prin a enuna o problem general i a trece n revist mai


muli algoritmi de rezolvare. Abia dup aceea vom descrie metoda programrii
dinamice.

7.1.

O problem general

Fie A i B dou mulimi oarecare.


Fiecrui element xA urmeaz s i se asocieze o valoare v(x)B.
Iniial v este cunoscut doar pe submulimea XA, X.
Pentru fiecare xA\X sunt cunoscute:
AxA :
mulimea elementelor din A de a cror valoare depinde v(x);
fx
funcie care specific dependena de mai sus. Dac
:
Ax={a1,...,ak}, atunci v(x)=fx(v(a1),...,v(ak)).
Se mai d zA.
Se cere s se calculeze, dac este posibil, valoarea v(z).
Exemplu.
A={1,2,...,13}; X={1,2,6,7,8,9,10};
A3={1,2};
A4={1,2,3};
A5={1,4};
A12={9,10};
A13={11,12}.
A11={7,8};
Elementele din X au asociat valoarea 1.
Fiecare funcie fx calculeaz v(x) ca fiind suma valorilor elementelor din
Ax. Alegem z=5.
Este evident c vom obine v=(1,1,2,4,5,1,1,1,1,1,2,2,4). O
ordine posibil de a considera elementele lui A\X astfel nct s putem calcula
valoarea asociat lor este: 3,11,12,13,4,5.

Lucrurile devin mai clare dac reprezentm problema pe un graf de


dependene. Vrfurile corespund elementelor din A, iar descendenii unui vrf x
sunt vrfurile din Ax. Vrfurile din X apar subliniate.

7. METODA PROGRAMRII DINAMICE

68

13

5
4

12

11

2
1

10

Problema enunat nu are totdeauna soluie, aa cum se vede pe graful de


dependene de mai jos, n care exist un circuit care nu permite calculul lui v n
z=3.
3
1
2

Observaii:
-

A poate fi chiar infinit;


B este de obicei N, Z, R, {0,1} sau un produs cartezian;
fx poate fi un minim, un maxim, o sum etc.

Pentru orice xA, spunem c x este accesibil dac, plecnd de la X, poate


fi calculat valoarea v(x). Evident, problema are soluie dac i numai dac z
este accesibil.
Pentru orice xA, notm prin Ox mulimea vrfurilor observabile din x,
adic mulimea vrfurilor y pentru care exist un drum de la y la x. Problema
enunat are soluie dac i numai dac:
1) Oz nu are circuite;
2) vrfurile din Oz n care nu sosesc arce fac parte din X.
Prezentm n continuare mai multe metode/ncercri de rezolvare a
problemei enunate.

7.2. Metoda irului cresctor de mulimi

7.2.

69

Metoda irului cresctor de mulimi

Fie A o mulime finit i X o submulime a sa. Definim urmtorul ir


cresctor de mulimi:
X0 = X
Xk+1 = Xk {x AAx Xk}, k>0
Evident, X0 X1 ... Xk Xk+1 ... A.

Propoziie. Dac Xk+1=Xk, atunci Xk+i=Xk ,iN.


Facem demonstraia prin inducie dup i.
Pentru i=1 rezultatul este evident.
Presupunem Xk+i=Xk i demonstrm c Xk+i+1=Xk :
Xk+i+1 = cf. definiiei irului de mulimi
=
=
=
=

Xk+i {x A AxXk+i} = cf. ipotezei de inducie


Xk {x A AxXk} = cf. definiiei irului de mulimi
Xk+1 = cf. ipotezei
Xk .

Consecine.
ne oprim cu construcia irului cresctor de mulimi la primul k cu Xk=Xk+1
(A este finit!);
- dac aplicm cele de mai sus pentru problema general enunat, aceasta
are soluie dac i numai dac zXk.
-

Prezentm n continuare algoritmul corespunztor acestei metode, adaptat


la problema general.
Vom lucra cu o partiie A=UV, unde U este mulimea curent de vrfuri a
cror valoare asociat este cunoscut.
U X; V A\X
repeat
W V
for toi xV
if AxU
then U U {x}; V V\{x}
calculeaz v(x) conform funciei fx
if x=z
then write v(x); stop
until V=W { nu s-a avansat! }
write(z, 'nu este accesibil)

7. METODA PROGRAMRII DINAMICE

70

Metoda descris are dou deficiene majore:


- la fiecare reluare se parcurg toate elementele lui V;
- nu este precizat o ordine de considerare a elementelor lui V.
Aceste deficiene fac ca aceast metod s nu fie performant.
Metoda irului cresctor de mulimi este larg folosit n teoria limbajelor
formale, unde de cele mai multe ori ne intereseaz existena unui algoritm i nu
performanele sale.

7.3.

Sortarea topologic

Fie A={1,...,n} o mulime finit. Pe A este dat o relaie tranzitiv,


notat prin "<". Relaia este dat prin mulimea perechilor (i,j) cu i<j.
Se cere s se listeze elementele 1,..,n ale mulimii ntr-o ordine ce
satisface cerina: dac i<j, atunci i apare la ieire naintea lui j.
Problema enunat apare, de exemplu, la nscrierea unor termeni ntr-un
dicionar astfel nct explicaiile pentru orice termen s conin numai termeni ce
apar anterior.
Este evident c problema se transpune imediat la grafurile de dependen:
se cere o parcurgere a vrfurilor grafului astfel nct dac exist un arc de la i la
j, atunci i trebuie vizitat naintea lui j.

Observaii:
problema are soluie dac i numai dac graful este aciclic;
dac exist soluie, ea nu este neaprat unic.

n esen, algoritmul care urmeaz repet urmtorii pai:


- determin i care nu are predecesori;
- l scrie;
- elimin perechile pentru care sursa este i.
Fie M mulimea curent a vrfurilor care nu au predecesori. Iniial M=X.
Mulimea M va fi reperezentat ca o coad, notat cu C.
Pentru fiecare iA, considerm:
Si = lista succesorilor lui i;
nrpredi = numrul predecesorilor lui i din mulimea M curent.

7.3. Sortarea topologic

71

Etapa de iniializare const n urmtoarele:


Si , nrpredi0, i
C ; nr 0
{ nr este numrul elementelor produse la ieire }
for k=1,m
{ m este numrul perechilor din relaia "<" }
read(i,j)
Si j; nrpredj nrpredj+1
for i=1,n
if nrpredi=0
then i C

S observm c timpul cerut de etapa de iniializare este de ordinul


O(m+n).
Algoritmul propriu-zis, adaptat la problema general, este urmtorul:
while C
i C; write(i); nr nr+1
calculeaz v(i) conform funciei fi
if i=z
then write(i,v(i)); stop
for toi jSi
nrpredj nrpredj-1
if nrpredj=0 then j C
if nr<n then write('Nu')

Fiecare executare a corpului lui while necesit un timp proporional cu


Si. Dar |S1|+...+|Sn|=m, ceea ce face ca timpul de executare s fie de
ordinul O(m). innd cont i de etapa de iniializare, rezult c timpul total este
de ordinul O(m+n), deci liniar.
Totui, sortarea topologic aplicat problemei generale prezint un
dezavantaj: sunt calculate i valori ale unor vrfuri "neinteresante", adic
neobservabile din z.

7.4.

ncercare cu metoda Divide et Impera


Este folosit o procedur DivImp, apelat prin DivImp(z).

procedure DivImp(x)
for toi yAx\X
DivImp(y)
calculeaz v(x) conform funciei fx
end;

7. METODA PROGRAMRII DINAMICE

72

Apare un avantaj: sunt parcurse doar vrfurile din Oz. Dezavantajele sunt
ns decisive pentru renunarea la aceast ncercare:
- algoritmul nu se termin pentru grafuri ciclice;
- valoarea unui vrf poate fi calculat de mai multe ori, ca de exemplu
pentru situaia:

7.5.
-

Soluie final
Etapele sunt urmtoarele:
identificm Gz = subgraful asociat lui Oz ;
aplicm sortarea topologic.
Fie Gz=(Xz,Mz). Iniial Xz=, Mz=.
Pentru a obine graful Gz executm apelul DF(z), unde procedura DF este:

procedure DF(x)
x Xz
for toi yAx
if yXz then (y,x) Mz; DF(y)
end;

Timpul este liniar.

Observaie. Ar fi totui mai bine dac :


am cunoate de la nceput Gz;
forma grafului ar permite o parcurgere mai simpl.

7.6. Metoda programrii dinamice


Definim un PDarbore de rdcin z ca fiind un graf de dependene,
aciclic, n care:
- x, xOz (pentru orice vrf x exist un drum de la x la z);
- X={xgrad-(x)=0} (vrfurile n care nu sosesc arce sunt exact cele din
submulimea X).

7.6. Metoda programrii dinamice

73

Exemplu. Urmtorul graf este un PD-arbore de rdcin z=5.


5

5
4

4
3

3
1

1
2
Un PD-arbore nu este neaprat un arbore, dar:
- poate fi pus pe niveluri: fiecare vrf x va fi pus pe nivelul egal cu
lungimea celui mai lung
- drum de la x la z, iar sensul arcelor este de la nivelul inferior ctre cel
superior;
- poate fi parcurs (cu mici modificri) n postordine;
Prin parcurgerea n postordine, vrfurile apar sortate topologic.
Algoritmul de parcurgere n postordine folosete un vector parcurs
pentru a ine evidena vrfurilor vizitate. Este iniializat vectorul parcurs i se
ncepe parcurgerea prin apelul postord(z):
for toate vrfurile xA
parcurs(x) xX
postord(z)

unde procedura postord cu argumentul x calculeaz v(x):


procedure postord(x)
for toi jAx cu parcurs(j)=false
postord(j)
calculeaz v(x) conform funciei fx; parcurs(x)true
end

Timpul de executare a algoritmului este evident liniar.


Metoda programrii dinamice se aplic problemelor care urmresc
calcularea unei valori i const n urmtoarele:
1) Se asociaz problemei un graf de dependene;
2) n graf este pus n eviden un PD-arbore; problema se reduce la
determinarea valorii asociate lui z (rdcina arborelui);
3) Se parcurge n postordine PD-arborele.

7. METODA PROGRAMRII DINAMICE

74

Mai pe scurt, putem afirma c:


Metoda programrii dinamice const n identificarea
unui PD-arbore i parcurgerea sa n postordine.
n multe probleme este util s cutm n PD-arbore regulariti care s
evite memorarea valorilor tuturor vrfurilor i/sau s simplifice parcurgerea n
postordine.
Vom ncepe cu cteva exemple, la nceput foarte simple, dar care pun n
eviden anumite caracteristici ale metodei programrii dinamice.
Exemplul 1. irul lui Fibonacci
tim c acest ir este definit astfel:
F0=0; F1=1;
Fn = Fn-1 + Fn-2 , n2
Dorim s calculm Fn pentru un n oarecare.

Aici A={0,...,n}, X={0,1}, B=N, iar


Ak={k-1,k-2}, k2
v(k)=Fk ; fk(a,b)=a+b, k2
Un prim graf de dependene este urmtorul:
0

1
2

. . . .
3

n-2

n-1

n=z

S observm c o mai bun alegere a mulimii B simplific structura PDarborelui.


A={1,2,...,n}; B=NN;
v(k)=(Fk-1, Fk); fk(a,b)=(b,a+b)
v(1)=(0,1).
1

i obinem algoritmul binecunoscut:


a0; b1
for i=2,n
(a,b)(b,a+b)
write(b)

n-1

7.6. Metoda programrii dinamice

75

Exemplul 2. Calculul sumei a1+ ...+an


Este evident c trebuie calculate anumite sume pariale.
O prim posibilitate este s considerm un graf n care fiecare vrf s fie o
submulime {i1,...,ik} a lui {1,2,...,n}, cu valoarea asociat
ai1 + ai2 +...+ aik . Aceast abordare este nerealizabil: numrul de vrfuri ar fi
exponenial.
O a doua posibilitate este ca vrfurile s corespund mulimilor
{i,i+1,...,j} cu ij i cu valoarea ataat si,j=ai+...+aj. Vom nota un
astfel de vrf prin (i:j). Dorim s calculm valoarea a1+...+an vrfului
z=(1:n). Putem considera mai muli PD-arbori:


Arborele liniar constituit din vrfurile cu i=1. Obinem relaiile de recuren:


s1,1=a1;
s1,j=s1,j-1+aj , j=2,3,...,n
care corespund asociativitii la stnga: (...((a1+a2)+a3)+...).


Arborele liniar constituit din vrfurile cu j=n. Acest arbore corespunde


asociativitii la dreapta a sumei:

sn,n=an
si,n=ai+si-1,n, i=n-1,n-2,...1.

Arborele binar strict n care fiecare vrf (afar de frunze) are descendenii
(i:k) i (k+1:j) cu k= (i+j)/2 . Prezentm acest arbore pentru n=7:
(1:7)

(1:4)

(3:4)

(1:2)

(1:1)

(2:2)

(5:7)

(3:3)

Relaiile de recuren sunt:


sii=ai
si,j=sik+sk+1,j pentru i<j.

(4:4)

(5:6)

(5:5)

(6:6)

(7:7)

7. METODA PROGRAMRII DINAMICE

76

iar algoritmul const n parcurgerea pe niveluri, de jos n sus, a arborelui; nu este


folosit vreun tablou suplimentar:
k 1
while k<n
k2k+k; i1
while i+kn
aiai+ai+k; ii+k2
k k2

Rezultatul este obinut n a1. Evoluia calculelor apare n urmtorul tabel:


n
7

k2
2

k
1

i
1
3
5
7
1
5
9
1
9

a1a1+a2
a3a3+a4
a5a5+a6
a1a1+a3
a5a5+a7
a1a1+a5

Algoritmul de mai sus nu este att de stupid i inutil pe ct apare la prima


vedere pentru o problem att de simpl.
ntr-adevr, calculele pentru fiecare reluare a ciclului while interior sunt
executate asupra unor seturi de date disjuncte. De aceea, n ipoteza c pe
calculatorul nostru dispunem de mai multe procesoare, calculele pe fiecare nivel
al arborelui (mergnd de jos n sus) pot fi executate n paralel. Drept urmare,
timpul de calcul va fi de ordinul O(log n), deci sensibil mai bun dect cel
secvenial, al crui ordin este O(n).
Exemplul 3. Determinarea subirului cresctor de lungime maxim.
Se consider vectorul a=(a1,...,an). Se cer lungimea celui mai lung
subir cresctor, precum i toate subirurile cresctoare de lungime maxim.
Introducem notaiile:
nr = lungimea maxim cutat;
lung(i)= lungimea maxim a subirului cresctor ce ncepe cu ai.
A={1,2,...,n};
X={n};
Ai={i+1,...,n} i fi=lung(i), i<n;
Evident, suntem n prezena unui PD-arbore de rdcin 1.

7.6. Metoda programrii dinamice

77

Determinarea lui nr se face astfel:


nr 1; lung(n) 1
for i=n-1,1,-1
lung(i) 1+max{lung(j)j>i & ai<aj}
nr max{nr,lung(i)}

Determinarea tuturor subirurilor cresctoare de lungime maxim se face


printr-un backtracking recursiv optimal. Subirurile se obin n vectorul s, iar ind
reprezint ultima poziie completat din s.
for i=1,n
if lung(i)=nr
then ind 1; s(1)ai; scrie(i)

unde procedura scrie are forma:


procedure scrie(i)
if ind=nr
then write(s)
else for j=i+1,n
if ai<aj & lung(i)=1+lung(j)
then indind+1; s(ind)a(j); scrie(j); indind-1
end;

Exemplul 4. nmulirea optim a unui ir de matrici.


Avem de calculat produsul de matrici A1A2...An, unde dimensiunile
matricilor sunt respectiv (d1,d2),(d2,d3),....,(dn,dn+1). tiind c nmulirea
matricilor este asociativ, se pune problema ordinii n care trebuie nmulite
matricile astfel nct numrul de nmuliri elementare s fie minim.
Presupunem c nmulirea a dou matrici se face n modul uzual, adic
produsul matricilor A(m,n) i B(n,p) necesit mnp nmuliri elementare.
Pentru a pune n eviden importana ordinii de nmulire, s considerm
produsul de matrici A1A2A3A4 unde A1(100,1), A2(1,100), A3(100,1),
A4(1,100).
Pentru ordinea de nmulire (A1A2)(A3A4) sunt necesare 1.020.000 de
nmuliri elementare. n schimb, pentru ordinea de nmulire (A1(A2A3))A4
sunt necesare doar 10.200 de nmuliri elementare.

7. METODA PROGRAMRII DINAMICE

78

Fie cost(i,j) numrul minim de nmuliri elementare pentru calculul


produsului Ai...Aj. Punnd n eviden ultima nmulire de matrici, obinem
relaiile:
cost(i,i) = 0, i=1,2,...,n
cost(i,j) = min {cost(i,k)+cost(k+1,j)+didk+1dj+1 | ik<j}.
Valoarea cerut este cost(1,n).

Vrfurile grafului de dependen sunt perechile (i,j) cu ij. Valoarea


cost(i,j) depinde de valorile vrfurilor din stnga i de cele ale vrfurilor de
deasupra. Se observ uor c suntem n prezena unui PD-arbore.
j

(i,i)

(i,j)
(j,j)

Forma particular a PD-arborelui nu face necesar aplicarea algoritmului


general de parcurgere n postordine: este suficient s parcurgem n ordine
coloanele 2,...,n, iar pe fiecare coloan j s mergem n sus de la diagonal pn la
(i,j).
for j=2,n
for i=j-1,1,-1
cost(i,j) calculat ca mai sus; fie k valoarea pentru care se realizeaz

minimul
cost(j,i)k
write cost(1,n)

(se observ c am folosit partea inferior triunghiular a matricii pentru a memora


indicii pentru care se realizeaz minimul).
Dac dorim s producem i o ordine de nmulire optim, vom apela
sol(1,n), unde procedura sol are forma:
procedure sol(p,u)
if p=u
then write(p)

7.6. Metoda programrii dinamice

79

else kcost(u,p)
write('('); sol(p,k); write(',');
sol(k+1,u); write(')')
end;

Pentru evaluarea timpului de lucru, vom calcula numrul de comparri


efectuate. Aceste este:
n j1

2)
] = O(n3)
[j(j 1) (j1)(j
2
n

(j i + 1)=

j=2 i =1

j=2

Exemplul 5. Descompunerea unui dreptunghi n ptrate


Se consider un dreptunghi cu laturile de m, respectiv n uniti (m<n).
Asupra sa se pot face tieturi complete pe orizontal sau vertical. Se cere
numrul minim de ptrate n care poate fi descompus dreptunghiul.
Fie aij = numrul minim de ptrate n care poate fi descompus un
dreptunghi de laturi i i j. Evident aij=aji. Rezultatul cutat este amn.
Vrfurile grafului de dependene sunt (i,j), iar valorile asociate sunt aij.
k

j-k

k
i
i-k
j

Pentru calculul lui aij avem de ales ntre a face:


- o tietur pe vertical; costurile sunt: aik+ai,j-k, k j/2 ;
- o tietur pe orizontal; costurile sunt: ak,j+ai-k,j, k i/2 .
Rezult c valoarea aij a unui vrf (i,j) depinde de valorile vrfurilor
din stnga sa i de cele aflate deasupra sa. Se observ c graful de dependene este
un PD-arbore.
j

(i,j)

7. METODA PROGRAMRII DINAMICE

80

Dependenele pot fi exprimate astfel:


ai,1=i, i=1,...,m
a1,j=j, j=1,...,n
aii=1, =1,...,m
aij = min{, }, unde
=min{aik+ai,j-k | k j/2} , iar =min{ak,j+ai-k,j | k i/2 }.

Forma particular a PD-arborelui permite o parcurgere mai uoar dect


aplicarea algoritmului general de postordine. De exemplu putem cobor pe linii,
iar pe fiecare linie mergem de la stnga la dreapta.
Dup iniializrile date de primele trei dependene de mai sus, efectum
calculele:
for i=2,m
for j=i+1,n

calculul lui aij conform celei de a patra dependene de mai sus


if jm then ajiaij

Observaie. Am lucrat numai pe partea superior triunghiular, cu


actualizri dedesubt.

8
8.1.

METODA BRANCH AND BOUND

Prezentare general

Metoda Branch and Bound se aplic problemelor care care pot fi


reprezentate pe un arbore: se ncepe prin a lua una dintre mai multe decizii
posibile, dup care suntem pui n situaia de a alege din nou dintre mai multe
decizii; vom alege una dintre ele etc. Vrfurile arborelui corespund strilor
posibile n dezvoltarea soluiei.
Deosebim dou tipuri de probleme:
1) Se caut un anumit vrf, numit vrf rezultat, care evident este final (nu are
descendeni).
2) Exist mai multe vrfuri finale, care reprezint soluii posibile, dintre care
cutm de exemplu pe cel care minimizeaz o anumit funcie.
Exemplul 1. Jocul 15 (Perspico).
Un numr de 15 plcue ptrate sunt incorporate ntr-un cadru 44, o
poziie fiind liber. Fiecare plcu este etichetat cu unul dintre numerele
1,2,...,15. Prin configuraie nelegem o plasare oarecare a plcuelor n cadru.
Orice plcu adiacent cu locul liber poate fi mutat pe acest loc liber. Dndu-se
o configuraie iniial i una final, se cere s determinm o succesiune de mutri
prin care s ajungem din configuraia iniial n cea final. Configuraiile iniial
i final pot fi de exemplu:
1
5
9
13

2
6
14

3
7
10
15

4
8
11
12

1
5
9
13

2
6
10
14

3
7
11
15

4
8
12

unde locul liber mai poate fi considerat drept coninnd plcua imaginar cu
eticheta 16.
Observaie. Mutarea unei plcue adiacente locului liber pe acel loc poate
fi gndit i ca mutarea locului liber pe o poziie adiacent.

82

8. METODA BRANCH AND BOUND

Prezentm nti o condiie de existen a unei succesiuni de mutri prin


care se poate trece de la configuraia iniial n cea final.
Cele 16 locauri sunt considerate ca fiind ordonate de la stnga la dreapta
i de jos n sus. Pentru plcua etichetat cu i definim valoarea n(i) ca fiind
numrul locaurilor care urmeaz celei pe care se afl plcua i care conin o
plcu a crei etichet este mai mic dect i. De exemplu pentru configuraia
iniial de mai sus avem:
n(8)=1; n(4)=0; n(16)=10; n(15)=1 etc.
Fie l i c linia i coloana pe care apare locul liber. Fie x{0,1} definit
astfel: x=0 dac i numai dac l+c este par. Se poate demonstra urmtorul
rezultat:
Propoziie. Fiind dat o configuraie iniial, putem trece din ea la
configuraia final de mai sus n(1)+n(2)+...+n(16)+x este par.
n continuare vom presupune c putem trece de la configuraia iniial la
cea final.
Cum locul liber poate fi mutat spre N, S, E, V (fr a iei ns din cadru),
rezult c fiecare configuraie (stare) are cel mult 4 descendeni. Se observ c
arborele astfel construit este infinit. Strile finale sunt stri rezultat i corespund
configuraiei finale.
Exemplul 2. Circuitul hamiltonian de cost minim.
Se consider un graf orientat cu arcele etichetate cu costuri pozitive.
Inexistena unui arc ntre dou vrfuri este identificat prin "prezena" sa cu costul
+. Presupunem c graful este dat prin matricea C a costurilor sale. Se cere s se
determine, dac exist, un circuit hamiltonian de cost minim.
S considerm, de exemplu, graful dat de matricea de costuri:
3 7 2

5 1 9
C =
4 8 3

6 2 6

Arborele spaiului de stri, n care muchiile corespund arcelor din graf,


este urmtorul:

8.1. Prezentare general

83

(1,2
)

(1,3)

(2,3)
5

(3,4)
11

(1,4)

(2,4)

(3,2)

(4,5)
12

(2,4)
13

(3,4)

(4,2)

(4,2)

(2,3)

14

15

(4,3)
10

(3,2)
16

subnelegndu-se c se pleac din vrful 1 i c din frunze se revine la acest vrf.


Revenim la descrierea metodei Branch and Bound.
tim c i metoda backtracking este aplicabil problemelor reprezentabile
pe arbori. Exist ns multe deosebiri, dintre care menionm urmtoarele:
- ordinea de parcurgere a arborelui;
- modul n care sunt eliminai subarborii care nu pot conduce la o soluie;
- faptul c arborele poate fi infinit (prin natura sa sau prin faptul c mai multe
vrfuri pot corespunde la o aceeai stare).
n general arborele de stri este construit dinamic.
Este folosit o list L de vrfuri active, adic de stri care sunt susceptibile
de a fi dezvoltate pentru a ajunge la soluie/soluii. Iniial, lista L conine rdcina
arborelui, care este vrful curent. La fiecare pas, din L alegem un vrf (care nu
este neaprat un fiu al vrfului curent!), care devine noul vrf curent.
Cnd un vrf activ devine vrf curent, sunt generai toi fiii si, care devin
vrfuri active (sunt inclui n L). Apoi din nou este selectat un vrf curent.
Legat de modul prin care alegem un vrf activ drept vrf curent, deci
implicit legat de modul de parcurgere a arborelui, facem urmtoarele remarci:
parcurgerea DF nu este adecvat, deoarece pe de o parte arborele poate fi
infinit, iar pe de alt parte soluia cutat poate fi de exemplu un fiu al rdcinii

84

8. METODA BRANCH AND BOUND

diferit de primul fiu i parcurgerea n adncime ar fi ineficient: se parcurg inutil


stri, n loc de a avansa direct spre soluie;
parcurgerea pe lime conduce totdeauna la soluie (dac aceasta exist), dar
poate fi ineficient dac vrfurile au muli fii.
Metoda Branch and Bound ncearc un "compromis" ntre cele dou
parcurgeri menionate mai sus, atand vrfurilor active cte un cost pozitiv, ce
intenioneaz s fie o msur a gradului de "apropiere" a vrfului de o soluie.
Alegerea acestui cost este decisiv pentru a obine un timp de executare ct mai
bun i depinde de problema concret, dar i de abilitatea programatorului.
Observaie. Costul unui vrf va fi totdeauna mai mic dect cel al
descendenilor (fiilor) si.
De fiecare dat drept vrf curent este ales cel de cost minim (cel considerat
ca fiind cel mai "aproape" de soluie). De aceea L va fi n general un minansamblu: costul fiecrui vrf este mai mic dect costul descendenilor.
Din analiza teoretic a problemei deducem o valoare lim care este o
aproximaie prin adaos a minimului cutat: atunci cnd costul unui vrf depete
lim, vrful curent este ignorat: nu este luat n considerare i deci este eliminat
ntregul subarbore pentru care este rdcin. Dac nu cunoatem o astfel de
valoare lim, o iniializm cu +.




-

Se poate defini o funcie de cost ideal, pentru care c(x) este dat de:
nivelul pe care se afl vrful x dac x este vrf rezultat;
+
dac x este vrf final, diferit de vrf rezultat;
dac x nu este vrf final.
min {c(y) | y fiu al lui x }
Aceast funcie este ideal din dou puncte de vedere:
nu poate fi calculat dac arborele este infinit; n plus, chiar dac arborele este
finit, el trebuie parcurs n ntregime, ceea ce este exact ce dorim s evitm;
dac totui am cunoate aceast funcie, soluia poate fi determinat imediat:
plecm din rdcin i coborm mereu spre un vrf cu acelai cost, pn
ajungem n vrful rezultat.

Neputnd lucra cu funcia ideal de mai sus, vom alege o aproximaie a


lui c, care trebuie s satisfac condiiile:
1) n continuare, dac y este fiu al lui x avem (x)<(y);
2) (x) s poat fi calculat doar pe baza informailor din drumul de la rdcin
la x;

8.1. Prezentare general

85

3) este indicat ca c pentru a ne asigura c dac (x)>lim, atunci i


c(x)>lim, deci x nu va mai fi dezvoltat.
O prim modalitate de a asigura compromisul ntre parcurgerile n
adncime i pe lime este de a alege funcia astfel nct, pentru o valoare
natural k, s fie ndeplinit condiia: pentru orice vrf x situat pe un nivel nx i
orice vrf situat pe un nivel nynx+k, s avem (x)>(y), indiferent dac y este
sau nu descendent al lui x.
Condiia de mai sus spune c niciodat nu poate deveni activ un vrf aflat
pe un nivel nynx+k dac n L apare un vrf situat pe nivelul nx, adic nu putem
merge "prea mult" n adncime. Dac aceast condiie este ndeplinit, este
valabil urmtoarea propoziie:
Propoziie. n ipoteza c este ndeplinit condiia de mai sus i dac exist
soluie, ea va fi atins ntr-un timp finit, chiar dac arborele este infinit.
Putem aplica cele de mai sus pentru jocul Perspico, alegnd:
(x) = suma dintre lungimea drumului de la rdcin la x i numrul de plcue
care nu sunt la locul lor (aici k=15).

8.2.

Algoritmul Branch & Bound pentru probleme de optim

S presupunem c dorim s determinm vrful final de cost minim i


drumul de la rdcin la el. Fie lim aproximarea prin adaos considerat mai sus.
Algoritmul este urmtorul (rad este rdcina arborelui, iar ifinal este
vrful rezultat):
i rad; L {i}; min lim;
calculm (rad); tata(i) 0
while L
i L {este scos vrful i cu (i) minim din min-ansamblul L}
for toi j fii ai lui i
calculm (j); calcule locale asupra lui j; tata(j) i
if j este vrf final
then if (j)<min
then min (j); ifinal j
elimin din L vrfurile k cu (k) min (*)
else if (j)<min
then j L

86

8. METODA BRANCH AND BOUND

if min=lim then write('Nu exist soluie')


else writeln(min); i ifinal
while i 0
write(i); i tata(i)

Observaie. La (*) am inut cont de faptul c dac j este descendent al lui


i, atunci (i)<(j).
Vom aplica algoritmul de mai sus pentru problema circuitului hamiltonian
de cost minim, pe exemplul considerat mai sus.
Pentru orice vrf x din arborele de stri, valoarea c(x) dat de funcia de
cost ideal este:
dac x este frunz
 lungimea circuitului corespunztor lui x
altfel.
 min {c(y) | y fiu al lui x }
Fiecrui vrf x i vom ataa o matrice de costuri Mx (numai dac nu este
frunz) i o valoare (x).
Observaie. Dac micorm toate elementele unei linii sau coloane cu ,
orice circuit hamiltonian va avea costul micorat cu , deoarece n orice circuit
hamiltonian din orice vrf pleac exact un arc i n orice vrf sosete exact un arc.
Conform acestei observaii, vom lucra cu matrici de costuri reduse (n care
pe orice linie sau coloan apare cel puin un zero, exceptnd cazul cnd linia sau
coloana conine numai ).
Pentru rdcina rad=1 plecm de la matricea de costuri C. Matricea
ataat va fi matricea redus obinut din C, iar (1) = cantitatea cu care s-a redus
matricea C.
n general, pentru un vrf y oarecare al crui tat este x i muchia (x,y)
este etichetat cu (i,j):
 dac y este vrf terminal, (x) va fi chiar c(y), adic costul
real al circuitului;
x
 n caz contrar, plecnd de la Mx i (x) procedm astfel:
- elementele liniei i devin , deoarece mergem sigur ctre
(i,j)
vrful j din graf;
- elementele coloanei j devin , deoarece am ajuns sigur n
y
vrful j din graf;
- Mx(j,1) , pentru a nu reveni prematur n rdcina 1;
- reducem noua matrice Mx i obinem My; fie r cantitatea cu
care s-a redus Mx. Vom lua (y) (x)+r+Mx(i,j).

8.2. Algoritmul Branch & Bound pentru probleme de optim

87

Concret, pentru exemplul dat, calculele se desfoar astfel:




Pentru rdcin:
- reducem liniile n ordine cu 2, 1, 3, 2;
- reducem prima coloan cu 1;
- n acest mod obinem (1)=9

1 5 0

3 0 8
M1 =
0 5 0

3 0 4

Acum min9; L={1}. Este extras vrful 1 i sunt considerai fiii si.


Pentru vrful 2:

- plecm de la M1 i punem pe linia 1 i coloana 2;

- elementul de pe linia 2 i coloana 1 devine ;


M2 =
0
- reducem linia 3 cu 3;

- n acest mod obinem (2)=9+3+1=13


0

0 8
0

Pentru vrful 3:

- plecm de la M1 i punem pe linia 1 i coloana 3;

- elementul de pe linia 3 i coloana 1 devine ;


0
M3 =
- reducem linia 2 cu 3;

- n acest mod obinem (3)=9+3+5=17


3

5
5 0

Pentru vrful 4:

- plecm de la M1 i punem pe linia 1 i coloana 4;

- elementul de pe linia 4 i coloana 1 devine ;


3
M4 =
- nu este necesar vreo reducere;
0

- n acest mod obinem (4)=9+0+0=9

0
5

0 4

Acum L={2,3,4} cu (2)=13, (3)=17, (4)=9. Devine activ vrful 4.




Pentru vrful 9:

- plecm de la M4 i punem pe linia 4 i coloana 2;

- elementul de pe linia 2 i coloana 1 devine ;

=
M
9
- nu este necesar vreo reducere;
0

- n acest mod obinem (9)=9+0+0=9

Pentru vrful 10:


- plecm de la M4 i punem pe linia 4 i coloana 3;

- elementul de pe linia 3 i coloana 1 devine ;


0
- reducem linia 2 cu 3, iar linia 3 cu 5;
M10 =
0

- n acest mod obinem (10)=9+8+4=21

88

8. METODA BRANCH AND BOUND

Acum L={2,3,9,10} cu (2)=13, (3)=17, (9)=9, (10)=21. Devine


activ vrful 9. Singurul su descendent este 15, care este frunz.
(15)=c(15)=9 (costul real al circuitului). Sunt eliminate din L vrfurile cu
costurile mai mari dect 9, deci L devine vid. min rmne egal cu 9, va fi
produs la ieire circuitul cutat (1,4,2,3,1) i algoritmul se oprete.

DRUMURI N GRAFURI

Fie G=(V,M) graf orientat cu n=|V|, m=|M|. Fie A matricea sa de


adiacen.
Considerm irul de matrici:
A 1 = A
k
A = A k-1A, k 2

a crui semnificaie este urmtoarea:


-

Propoziia 1. Ak(i,j) = numrul drumurilor de lungime k de la i la j.


pentru k=1: evident.

k-1 k : A k(i,j)= A k1(i,s) A(s,j), unde s este penultimul vrf din

s=1

drumul de la i la j; pentru fiecare s cu A(s,j)=1, la sum se adaug


numrul drumurilor de lungime k-1 de la i la s, adic numrul drumurilor de
lungime k de la i la j avnd pe s ca penultim vrf.
n continuare dorim s determinm numai existena drumurilor de lungime
k. Considerm irul de matrici:
A(1) = A
(k)
= A(k -1) o A, k 2
A
n

unde A(k)(i,j)= A(k1)(i,s) A(k1)(s,j)


s=1

a crui semnificaie este urmtoarea (elementele matricilor sunt 0 sau 1):


Propoziia 2. A(k)(i,j)=1 exist drum de lungime k de la i la j.
Demonstraia se face prin inducie ca mai sus.
Definim matricea drumurilor D prin:
D(i,j)=1 drum de la i la j.
D=A(1)...A(n-1), deoarece dac exist un drum de la i la j, exist i un
drum de lungime cel mult egal cu n-1 de la i la j.
Construciile matricilor de mai sus necesit un timp de ordinul O(n4).

9. DRUMURI N GRAFURI

90

Vom cuta s obinem un timp de executare mai bun, inclusiv pentru cazul
n care lungimea arcelor este oarecare (n cele de mai sus s-a presupus implicit c
arcele au lungimea egal cu 1).
n continuare, fiecare arc <i,j> va avea o etichet et(<i,j>) strict
pozitiv, ce reprezint lungimea arcului.
et(< i,j >) dac < i,j > M

Considerm P(i,j)= 0
dac i = j
+
altfel

i irul de matrici:
P0 = P

Pk(i,j)= min{Pk1(i,j),Pk1(i,k)+ Pk1(k,j)}, k 1

Propoziia 3. Pn este matricea celor mai scurte drumuri.


Vom demonstra prin inducie dup k urmtoarea afirmaie:
Pk(i,j) = lungimea celui mai scurt drum de la i la j n care numerele de ordine
ale nodurilor intermediare sunt cel mult egale cu k.
- pentru k=0: evident (nu exist vrfuri intermediare).
- k-1 k : Considerm un drum de lungime minim de la i la j.
Dac drumul nu trece prin k, Pk(i,j)=Pk-1(i,j).
Dac drumul trece prin k, el va trece o singur dat prin k (are lungime
minim) i n drumurile de lungime minim de la i la k i de la k la j vrful k
nu apare ca vrf intermediar, deci Pk(i,j)=Pk-1(i,k)+Pk-1(k,j).
i

Observaii:
1) s-a folosit metoda programrii dinamice;
2) Pk(i,i)=0;
3) Pk(i,k)=Pk-1(i,k) i Pk(k,j)=Pk-1(k,j), deci la trecerea de la Pk-1 la
Pk linia k i coloana k rmn neschimbate.
Rezult c putem folosi o singur matrice. Ajungem astfel la algoritmul
Floyd-Warshall:
for k=1,n
for i=i,n
for j=1,n
P(i,j) min {P(i,j),P(i,k)+P(k,j)}

Timpul de executare este evident de ordinul O(n3).

9. DRUMURI N GRAFURI

91

Dac dorim s determinm doar existena drumurilor i nu lungimea lor


minim, vom proceda similar. Considerm irul de matrici:
A 0 = A

A k(i, j) = A k 1(i, j) [A k 1(i, k) A k 1(k, j)]

, k 0

Propoziia 4. An este matricea drumurilor.


Demonstrm prin inducie dup k urmtoarea afirmaie:
Ak(i,j)=1 drum de la i la j cu numerele de ordine ale vrfurilor
intemediare egale cu cel mult k.
- pentru k=0: evident;
- k-1 k:
Dac Ak(i,j)=1, atunci fie Ak-1(i,j)=1, fie Ak-1(i,k)=Ak-1(k,j)=1; n
ambele situaii va exista, conform ipotezei de inducie, un drum de la i la j cu
numerele de ordine ale vrfurilor intemediare egale cu cel mult k.
Dac exist un drum de la i la j cu numerele de ordine ale vrfurilor
intemediare egale cu cel mult k, prin eliminarea ciclurilor drumul va trece cel
mult o dat prin k. Este suficient n continuare s considerm cazul n care
drumul trece prin vrful k i cazul n care drumul nu trece prin k.
Sunt valabile aceleai observaii ca la Propoziia 3, iar algoritmul are o
form similar:
DA
for k=1,n
for i=1,n
for j=1,n
D(i,j) D(i,j) [D(i,k)D(k,j)]
Timpul de executare este evident de ordinul O(n3).

n continuare ne vor interesa numai drumurile ce pleac dintr-un vrf x0


fixat. Este de ateptat ca timpul de executare s scad.
Mai precis, cutm d(x) = lungimea drumului minim de la x0 la x, pentru
orice vrf x. n plus, dorim s determinm i cte un astfel de drum.
Prezentm n continuare algoritmul lui Dijkstra pentru problema enunat.
Pentru simplificare, presupunem c orice vrf este accesibil din x0.
Pentru regsirea drumurilor vom folosi vectorul tata.
Perechiile (d(x),tata(x)) sunt iniializate astfel:
- (0,0)
pentru x=x0;
- (et(<x0,x>),x0)
dac <x0,x>M;
altfel.
- (+,0)

9. DRUMURI N GRAFURI

92

Fie T = mulimea vrfurilor x pentru care d(x) are valoarea final.


n continuare, algoritmul lucreaz astfel:
T {x0}
while TV
Fie xV\T cu d(x) minim
T T{x}
for toi xT
if d(x)>d(x)+et(<x,x>)
then d(x) d(x)+et(<x,x>); tata(x)x

(*)

Pentru a demonstra corectitudinea algoritmului, vom arta prin inducie


dup |T| c:
1) xT : d(x) = lungimea celui mai scurt drum de la x0 la x;
2) xT : d(x) = lungimea celui mai scurt drum de la x0 la x, ce trece
numai prin vrfuri din T.
T

Pentru |T|=1, concluzia este evident.


x0
|T| |T|+1: Fie x' vrful nou adugat.
x'
Demonstrm cele dou afirmaii de mai sus:
1) d(x) este cel final:
Presupunem prin absurd c exist un drum de la x0 la x de lungime mai
mic dect d(x). Acest drum trebuie s treac printr-un vrf yT.
x0

x'
yT

Evident d(y)<d(x). Contradicie, pentru c a fost ales x cu d(x)


minim.
2) Evident, conform actualizrilor (*) efectuate de algoritm.
Observaii.
1) Timpul de executare este de ordinul O(n2).
2) Pe baza vectorului tata, putem regsi pentru orice xV drumul minim ce
l leag de x0 n timp liniar. Regsirea tuturor acestor drumuri necesit un
timp de ordinul O(n2), deci complexitatea n timp a algoritmului nu
crete.
3) Dac dorim s aflm numai drumul minim de la x0 la un vrf x1 dat, ne
oprim cnd x=x1; aceasta nu implic ns o reducere a ordinului de
mrime al timpului de calcul.
4) Algoritmul de mai sus poate fi ncadrat la metoda Greedy, dar i la metoda
irului cresctor de mulimi.

Potrebbero piacerti anche