Sunteți pe pagina 1din 89

PROF.UNIV.DR.

HORIA IOAN GEORGESCU






TEHNICI AVANSATE DE
PROGRAMARE










1.1. 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.

DESPRE ALGORITMI
1
6 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=a
a
, unde a= 2 .
Dac xQ, propoziia este demonstrat.
Dac xQ, atunci x
a
=a
2
=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 7


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)=n
k
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 corectitudinii algoritmilor, exist dou aspecte
importante:

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.
8 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)=2d
2
, unde a=d i
b=d. Atunci (u+v)/2=d=ab/d=[a,b].
3) Terminarea programului:
Fie {x
n
}, {y
n
}, {u
n
}, {v
n
} irul de valori succesive ale variabilelor. Toate
aceste valori sunt numere naturale pozitive. Se observ c irurile {x
n
} i
{y
n
} sunt descresctoare, iar irul {x
n
+y
n
} 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 9

- 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 y p
54 12 0
27 24
13 48 24
6 96 72
3 192
1 384 264
0 ? 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 {x
n
}, {y
n
} irul de valori succesive ale variabilelor corespunztoare.
Se observ c irul {x
n
} este strict descresctor. Aceasta ne asigur c
dup un numr finit de pai vom obine x=0.
10 1. DESPRE ALGORITMI


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(a
1
,a
2
,...,a
n
).
Algoritmul binecunoscut este urmtorul:
m a
1

for i=2,n
if a
i
<m then m a
i

care necesit n-1 comparri ntre elementele vectorului a=(a
1
,a
2
,...,a
n
).

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
a
1
cu a
2
i c a
1
<a
2
. Atunci m=min(a
1
,a
3
,...,a
n=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(a
1
,a
2
,...,a
n
) i
M=max(a
1
,a
2
,...,a
n
).
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 a
1
; M a
1
; k 1
else if a
1
<a
2
then m a
1
; M a
2

else m a
2
; M a
1

k 2
{ k = numrul de elemente analizate }
while kn-2
if a
k+1
<a
k+2
then if a
k+1
<m then m a
k+1

if a
k+2
>M then M a
k+2

else if a
k+2
<m then m a
k+2

if a
k+1
>M then M a
k+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/2(-
2.
- 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,k-
1);
- prin k-1 comparri ntre perechi de elemente din C ajungem la (0,1,1,n-
2).
n total au fost necesare k+(k-1)+(k-1)=3k-2=3n/2(-2 comparri.
1.6. Existena algoritmilor 13


1.6. 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:
- x
1
,x
2
,... care constituie datele de intrare (nu exist instruciuni de citire);
- y (n care va aprea rezultatul prelucrrilor);
- z
1
,z
2
,... care constituie variabile de lucru.
Variabilele y,z
1
,z
2
,... 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
x
1
,x
2
,... 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 x
1
,x
2
,...,x
n
,
numrul y poate fi "calculat" pe baza lor dac i numai dac exist un program
n limbajul S care pentru valorile de intrare x
1
,x
2
,...,x
n
produce la
terminarea sa valoarea y.
Cu alte cuvinte, nelegem prin algoritm ce calculeaz valoarea y plecnd
de la valorile x
1
,x
2
,...,x
n
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.




ARBORI



2.1. 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 (i
1
,i
2
),(i
2
,i
3
),...,(i
k-1
,i
k
),
notat i prin (i
1
,i
2
,...,i
k
). Dac toate vrfurile drumului sunt distincte,
atunci el se numete drum elementar.
Un ciclu elementar este un drum (i
1
,i
2
,...,i
k
,i
1
), cu
(i
1
,i
2
,...,i
k
) drum elementar i k3. Un ciclu este un drum
(i
1
,i
2
,...,i
k
,i
1
) care conine cel puin un ciclu elementar.

Exemplul 1. n graful alturat:
- (1,2,5,4) este un drum de la 1 la 4;
- (5,2,1,4,5) este un ciclu elementar;
- (1,2,1) nu este un ciclu.

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}.
5
3
4
2
1
2
16 2. ARBORI






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.
6
5
3
2 1
4
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.











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.
10
1
9
10 8 1
7 3 9 2
6
4
5
3
2
1
0
7
3
6
5
4
2
8
18 2. ARBORI


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:











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:
7 6 4
5
3
9
8
2
1
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
20 2. ARBORI

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=(a
1
,...,a
n
) 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 a
i
.

Pentru 2
k-1
n<2
k
arborele va avea k niveluri, dintre care numai ultimul
poate fi incomplet (pe fiecare nivel i<k-1 se afl exact 2
i
vrfuri).











Vectorul a se numete ansamblu dac pentru orice i avem a
i
a
2i
i
a
i
a
2i+1
(dac fiii exist).
0
1
k-2
k-1
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 a
i
pn ajunge ntr-un vrf ai crui descendeni au valorile
mai mici dect a
i
. Acest lucru este realizat de procedura combin.

procedure combin(i,n)
j 2i; b a
i

while jn
if j<n & a
j
<a
j+1
then jj+1
if b>a
j

then a
j/2
b; exit
else a
j/2
a
j
; j 2j
a
j/2
b
end

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:


















Sortarea vectorului a se va face prin apelul succesiv al procedurilor
creare i sortare prezentate n continuare.
n i j b
12 1 2
4
3
a
1
12
5
10

a
2
8
11
22

a
5
4

a
11
3
i
2i+1 2i
ans ans
7 4
12 11 10 9 8
6 5
3
2
1
3
12 11
8
6
1 5 2 4
9 10
7
22 2. ARBORI

Procedura creare transform vectorul ntr-un ansamblu; n particular n
a
1
se obine cel mai mare element al vectorului.
Procedura sortare lucreaz astfel:
- pune pe a
1
pe poziia n i reface ansamblul format din primele n-1 elemente;
- pune pe a
1
pe poziia n-1 i reface ansamblul format din primele n-2
elemente;
- etc.

procedure creare procedure sortare
for i=n/2,1,-1 for i=n,2,-1
combin(i,n) a
1
a
i
; combin(1,i-1)
end 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:








Observaie. Parcurgerea n inordine a unui arbore de cutare produce
informaiile ataate vrfurilor n ordine cresctoare.

Fie a=(a
1
,...a
n
) 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.
11
5 20
17
15 18
7
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) :


24 2. ARBORI

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:










13 10 11 12
9 8 7 6 5
4 3 2
1
3
2
1
0
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).




26 2. ARBORI

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.




GRAFURI



3.1. 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 i
0
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 L
i
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 i
0
se pot vizita numai vrfurile din
componenta conex a lui i
0
. De aceea, n cazul n care graful nu este conex, dup
parcurgerea componentei conexe a lui i
0
vom repeta apelul DF pentru unul dintre
eventualele vrfuri nc neatinse.

procedure DF(i)
ndf ndf+1; nrdf(i) ndf; vizit(i);
for toi jL
i

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
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:








cu urmtoarele liste ale vecinilor vrfurilor:
L
1
={4,2,3}; L
2
={1,4}; L
3
={1,5};
L
4
={1,2,5}; L
5
={3,4}; L
6
={8,9};
L
7
={9}; L
8
={6} L
9
={6,7}

1
2
3
4
5
6
7
8
9
30 3. GRAFURI


30
pdurea DF este format din urmtorii arbori pariali corespunztori
componentelor conexe:










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)=|L
i
|; 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:


1
2
3
4
5
6
7
8
9
3.1. Parcurgerea DF a grafurilor neorientate 31


procedure DF(i)
ndf ndf+1; nrdf(i) ndf; vizit(i);
for toi jL
i

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.

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).


3.2. 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


32
Vom folosi matricea de adiacen a de ordin n n care a
ij
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 v
i
,
care este true dac i numai dac vrful corespunztor a fost atins n timpul
parcurgerii; iniial toate aceste valori sunt false. Vom pune a
ij
=2 pentru toate
muchiile de avansare.

v
i
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)
v
i
true; ndf ndf+1
for j=1,n
if a
ij
=1 & not v
j

then a
ij
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 a
ij
=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 a
ij
=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 G
1
=(X
1
,M
1
) i G
2
=(X
2
,M
2
) dou grafuri. Definim suma lor circular
ca fiind graful:
G
1
G
2
= (X
1
X
2
,M
1
M
2
\M
1
M
2
)

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

Exemple.
34 3. GRAFURI


34







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








(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:








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:






1
2
3
4
5
=
1
2
3 5
1
3
4
1 3 5
4
8
4
8
7
6
4
2
3 1
7
6
2
3 1
8
7
6 5
4
3
2
1
8
7
6 5
4
3
2
1
1
2
3
4
5
Arborele parial A: 1
2
3
4
5
3.3. Circuitele fundamentale ale unui graf 35


Demonstraie.
Considerm un ciclu n G, ale crui muchii sunt partiionate n
C={e
1
,...,e
k
}{e
k+1
,...,e
j
} unde e
1
,...,e
k
sunt corzi, iar e
k+1
,...,e
j

sunt muchii din A.
Fie C(e
1
),...,C(e
k
) ciclurile fundamentale din care fac parte
e
1
,...,e
k
. Fie C=C(e
1
)... C(e
k
). 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 e
1
,...,e
k
.
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 e
1
,...,e
k
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 = (u
1
=i, u
2
=tata(u
1
), ... , u
nu
=tata(u
nu-1
)=rad)
v = (v
1
=j, v
2
=tata(v
1
), ... , v
nv
=tata(v
nv-1
)=rad).
2) Parcurgem simultan vectorii u i v de la dreapta la stnga i determinm
cel mai mic indice k cu u
k
=v
k
.
Atunci ciclul cutat este:
u
1
=i, u
2
, ... , u
k
=v
k
, v
k-1
, ... , v
1
=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
36 3. GRAFURI


36
componentelor sale biconexe, unde prin component biconex (sau bloc) se
nelege un subgraf biconex maximal.

Exemplu: Componentele biconexe ale grafului:











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






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):

i nrdf(i) v(i)
1 1 1
2 2 1
3 8 1
4 9 1
5 3 1
6 4 3
7 5 3
8 6 6
9 7 2


1
2
5
9
3
1
4
5
7
6
5
8
1
2
3
4
5
6
7
8 9
1
2 3
4
5
8
6
7
8
9
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:












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 }.



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 ntr-
un acelai ciclu elementar cu i.

i
k
i
j
NU
38 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 jL
i

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:








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 i
0
rdcina arborelui DF, atunci pentru
orice fiu j al lui i
0
avem v(j)nrdf(i
0
) deoarece nici o muchie de ntoarcere
cu o extremitate n j nu poate avea cealalt extremitate "mai sus" dect i
0
. Drept
urmare, dup ce se coboar pe muchia de avansare (i
0
,j), se continu
parcurgerea DF i se revine n i
0
, vor fi nlturate din stiv toate muchiile din
i
j
NU
40 3. GRAFURI


40
componenta biconex ce conine (i
0
,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:











obinem pdurea:













i vectorul nrdf = (1,2,3,4,5,6,7,8,9,10,11).
9
1
2
3
4
5
6
7 8
10
11
5
1
2
3
4
6
7
8
9
10
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 i
0
un vrf al su. n unele situaii se pune
probleme determinrii vrfului j cel mai apropiat de i
0
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 i
0
. Este generalizat parcurgerea pe
42 3. GRAFURI


42
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 i
0
:

for i=1,n
vizitat(i) false
C ; C i
0
; vizitat(i
0
) 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.1. Descrierea metodei Greedy

Metoda Greedy (greedy=lacom) este aplicabil problemelor de optim.
Considerm mulimea finit A={a
1
,...,a
n
} i o proprietate p definit pe
mulimea submulimilor lui A:
p:P(A){0,1} cu

= =
=
X Y 1, p(Y) 1 p(X)
1 ) p(

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{a
i
})=1
then SS{a
i
}

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);
METODA GREEDY

4
44 4. METODA GREEDY

- 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={a
1
,...,a
n
}. 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 a
i
>0
then kk+1; s
k
a
i

write(s)

Exemplul 2. Se cere cel mai lung ir strict cresctor cu elemente din
vectorul a=(a
1
,...,a
n
).

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; s
1
a
1
; lung1; baza1
for i=2,n
if a
i
>s
k
then kk+1; s
k
a
i

else if k>lung then lungk; bazai-k
k1; s
1
a
i


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={a
1
,...,a
n
} 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 45


4.2. 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 pS
n
.
Pentru o astfel de permutare (ordine de aezare a textelor pe band), timpul
necesar pentru a citi textul de pe poziia k este: T
p
(k)=L(p
1
)+...+L(p
k
).
Presupunnd textele egal probabile, problema const n determinarea unei
permutri p care minimizeaz funcia de cost:
=
=
n
1 k
p
(k) T
n
1
T(p) .
S observm c funcia T se mai poate scrie: + =
=
n
1 k
k
) 1)L(p k (n
n
1
T(p)
(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 pS
n
optim, adic p minimizeaz funcia T. Dac p este diferit de
permutarea identic, atunci i<j cu L(p
i
)>L(p
j
):



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



Atunci n[T(p)-T(p)] = (n-i+1)L(p
i
) + (n-j+1)L(p
j
) -
- (n-i+1)L(p
j
) - (n-j+1)L(p
i
) =
= (j-i)L(p
i
)+(i-j)L(p
j
) =
= (j-i)[L(p
i
)-L(p
j
)]>0
ambii factori fiind pozitivi.
Rezult c T(p)<T(p). Contradicie.

) p=( p
i

p
j

p'=( p
j

p
i

)
46 4. METODA GREEDY


4.3. Problema continu a rucsacului

Se consider un rucsac de capacitate (greutate) maxim G i n obiecte
caracterizate prin:
- greutile lor g
1
,...,g
n
;
- ctigurile c
1
,...,c
n
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.
Prin soluie nelegem un vector x=(x
1
,...,x
n
) cu



=
G x g
i [0,1], x
n
1 i
i i
i

O soluie optim este o soluie care maximizeaz funcia =
=
n
1 i
i i
x c f(x) .

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

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 g
i
G1 then x
i
1; G1G1-g
i

else x
i
G1/g
i
;
for j=i+1,n
x
j
0
stop
write(x)

Am obinut deci x=(1,...,1,x
j
,0,...,0) cu x
j
[0,1).
Artm c soluia astfel obinut este optim.
4.3. Problema continu a rucsacului 47


Fie y soluia optim: y=(y
1
,...,y
k
,...,y
n
) cu

=
=
=
n
1 i
i i
n
1 i
i i
y c
G y g
maxim

Dac yx, fie k prima poziie pe care y
k
x
k
.

Observaii:
kj: pentru k>j se depete G.
y
k
<x
k
:
pentru k<j: evident, deoarece x
k
=1;
pentru k=j: dac y
k
>x
k
se depete G.
Considerm soluia: y=(y
1
,...,y
k-1
,x
k
,y
k+1
,...,y
n
) cu <1
(primele k-1 componente coincid cu cele din x). Pstrm greutatea total G, deci:
g
k
x
k
+(g
k+1
y
k+1
+...+g
n
y
n
)=g
k
y
k
+g
k+1
y
k+1
+...+g
n
y
n
. Rezult:
g
k
(x
k
-y
k
)=(1-)(g
k+1
y
k+1
+...+g
n
y
n
) (**)
Comparm performana lui y' cu cea a lui y:
f(y)-f(y) = c
k
x
k
+c
k+1
y
k+1
+...+ c
n
y
n
- (c
k
y
k
+c
k+1
y
k+1
+...+c
n
y
n
) =
= c
k
(x
k
-y
k
) + (-1)(c
k+1
y
k+1
+...+c
n
y
n
) =
= c
k
/g
k
[g
k
(x
k
-y
k
)+(-1)(g
k
/c
k
c
k+1
y
k+1
+...+g
k
/c
k
c
n
y
n
)]
Dar -1>0 i g
k
/c
k
g
s
/c
s
, s>k, conform (*). Atunci:
f(y)-f(y)>c
k
/g
k
[g
k
(x
k
-y
k
)+(-1)(g
k+1
y
k+1
+...+g
n
y
n
)]=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. ntr-
adevr, 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.


48 4. METODA GREEDY

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.


1 2 2
1 4 2
4 5 2
1 5 3
3 4 4
2 5 5
2 3 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 r
i
care identific
componenta conex (arborele) din care face parte vrful n soluia parial.
Atunci:
1 2
3
4
5
2
5
4
2
3
5
2
4.4. Problema arborelui parial de cost minim 49

- o muchie (i,j) va forma un ciclu cu precedentele r
i
=r
j
;
- la alegerea (adugarea) unei muchii (i,j) vom pune r
k
r
j
pentru orice
vrf k cu r
k
=r
i
(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.

r
i
i, i=1,n
l 1; nm 0; cost 0
while lm & nm<n-1
i1 mat(l,1); i2 mat(l,2)
r1 r
i1
; r2 r
i2

if r1r2
then nm nm+1; cost cost+mat(l,3);
write(i1,i2)
for k=1,n
if r
k
=r2 then r
k
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
50 4. METODA GREEDY

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.









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(n
k
) 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 n
3
, 2
n
i 3
n
operaii, pentru diferite valori mici ale lui n:



n=20 n=40 n=60
n
3


0,2 sec
2
n
1 sec 12,7 zile 366 secole
3
n
58 min 3855 secole 10
13
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=X
1
... X
n
. 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 x
k
dect dac am stabilit valori pentru
x
1
,...,x
k-1
i
k-1
(x
1
,...,x
k-1
)=1. Funciile
k
:X
1
...X
k
{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 x
k
:
METODA BACKTRACKING

5
52 5. METODA BACKTRACKING


1) Atribuie i avanseaz: mai sunt valori neconsumate (neanalizate) din
X
k
i valoarea x
k
aleas satisface
k
se mrete k.
2) ncercare euat: mai sunt valori neconsumate din X
k
i valoarea x
k

aleas dintre acestea nu satisface
k
se va relua, ncercndu-se
alegerea unei noi valori pentru x
k
.
3) "Revenire": nu mai exist valori neconsumate din X
k
(X
k
epuizat)
ntreaga X
k
devine disponibil i kk-1.
4) "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 C
k
X
k
mulimea valorilor consumate din X
k
. Algoritmul este
urmtorul:

C
i
, i;
k1;
while k>0
if k=n+1
then retsol(x); kk-1; { revenire dup obinerea unei soluii }
else if C
k
X
k

then alege vX
k
\C
k
; C
k
C
k
{v};
if
k
(x
1
,...,x
k-1
,v)=1
then x
k
v; kk+1; { atribuie i avanseaz }
else { ncercare euat }
else C
k
; kk-1; { revenire }

Pentru cazul particular X
1
=...=X
n
={1,...,s}, algoritmul se simplific
astfel:

k1; x
i
0, i=1,...,n
while k>0
if k=n+1
then retsol(x); kk-1; { revenire dup obinerea unei soluii }
else if x
k
<s
then x
k
x
k
+1;
if
k
(x
1
,...,x
k
)=1
then kk+1; { atribuie i avanseaz }
else { ncercare euat }
else x
k
0; kk-1; { revenire }
5.2. Exemple 53



5.2. 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 x
k
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) & x
i
=x
k

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 x
k
coloana pe care
este plasat dama de pe linia k.
Damele de pe liniile i i k sunt:
- pe aceeai coloan: dac x
i
=x
k
;
- pe aceeai diagonal: dac |x
i
-x
k
|=k-i.

function cont(k:integer): boolean;
b true; i 1;
while b and i<k
if |x
i
-x
k
|=k-i or x
i
=x
k

then b false
else i i+1;
cont b
end;
54 5. METODA BACKTRACKING



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 x
i
al i-lea vrf din ciclu.
Un vector x=(x
1
,...,x
n
) este soluie dac:
1) x
1
=1 i
2) {x
2
,...,x
n
}={2,...,n} i
3) x
i
,x
i+1
vecine, i=1,...,n-1 i
4) x
n
,x
1
vecine.
Vom considera c graful este dat prin matricea sa de adiacen.

function cont(k:integer):boolean;
if a(x
k-1
,x
k
)=0
then cont false
else i 1; b true;
while b & (i<k)
if x
k
=x
i
then b false
else i i+1
if k=n then b b a(x
n
,x
1
)=1
cont b
end


5.3. Esena metodei Backtracking

Metoda backtracking poate fi descris astfel:






Rolul condiiilor de continuare este ilustrat n figura ce urmeaz. Dac
pentru x
k
este aleas o valoare ce nu satisface condiiile de continuare, atunci la
parcurgerea n adncime este evitat parcurgerea unui ntreg subarbore.
Backtracking = parcurgerea limitat
*)
n adncime a unui arbore

*)
conform condiiilor de continuare
5.3. Esena metodei Backtracking 55
























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=(a
1
,...,a
n
)Z
n
. Cutm un subir strict cresctor
de lungime maxim.
Cutm deci indicii x
1
,...,x
k
care satisfac condiiile:
1) 1x
1
<...<x
k
n
2)
1
x
a <
2
x
a < . . . <
k
x
a
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).

x
1
x
2
x
k
56 5. METODA BACKTRACKING


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

Completm la capetele irului cu - i + :
a
0
-; nn+1; a
n
+;

Funcia cont are urmtoarea form:
function cont(k)
cont
1 - k
x
a <
k
x
a

end;

Procedura retsol are forma:
procedure retsol(k)
if k>kf then xfx; kfk;
end;

Algoritmul backtracking se modific astfel:

k1; x
0
0; x
1
0; kf0;
while k>0
if x
k
<n
then x
k
x
k
+1;
if cont(k)
then if x
k
=n { a
n
=+ }
then retsol(k); kk-1
else kk+1; x
k
x
k-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 X
1
=...=X
n
={1,...,s}.
Apelul iniial este: back(1).

procedure back(k)
if k=n+1
then retsol
else for i=1,s
x
k
i;
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:
a
1
( ; dif1; back(2);
Procedura back are urmtoarea form:

procedure back(k)
if k=n+1
then retsol {scrie soluia}
else a
k
( ; dif++;
if dif n-k then back(k+1)
dif--;
a
k
); 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: a
ij
=0;
- ocupate: a
ij
=1.
Se mai d o poziie (i
0
,j
0
). Se caut toate drumurile care ies n afara
matricii, trecnd numai prin poziii libere.

Variante:
- cum putem ajunge ntr-o poziie (i
1
,j
1
) dat?
- se cere determinarea componentelor conexe.
58 5. METODA BACKTRACKING


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:
depl =
|
|

\
|


1 0 1 0
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 a
ij
=-1 (a fost atins),
continum i apoi repunem a
ij
0 (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 a
p
,...,a
u
, 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.

u
p
6
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=(a
1
, ...,a
n
) 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
=-, a
n+1
=+ . Cutm perechea (b,i) dat de:
(true,i) dac a
i
=x;
(false,i) dac a
i-1
<x<a
i
.

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 a
i
>x : u i-1
a
i
=x : write(true,i); stop
a
i
<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;
62 6. METODA DIVIDE ET IMPERA


pentru 2 elemente, adic pentru u=p+1: se alege i=p. Dac x<a
i
, atunci
up-1. Se observ c se iese din ciclul while i a
i-1
<x<a
i
=a
p
;
pentru un element, adic p=u: se alege i=p=u. Dac x<a
i
atunci up-1, iar
dac x>a
i
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 2
n
-1.


6.4. Sortarea prin interclasare

Fie a=(a
1
,...,a
n
) 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 (a
p
,...,a
m
) i (a
m+1
,...,a
u
) sunt
ordonai cresctor, procedura Inter va ordona cresctor ntreaga secven
(a
p
,...,a
u
).
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 a
k1
i a
k2
n vectorul auxiliar b.

procedure Inter(p,m,u)
k1p; k2m+1; k3p;
while k1m & k2u
if a
k1
<a
k2
then b
k3
a
k1
; k1k1+1
else b
k3
a
k2
; k2k2+1
k3k3+1
if k1>m { au fost epuizate elementele primei subsecvene }
then for i=k2,u
b
k3
a
i
; k3k3+1
else for i=k1,m
b
k3
a
i
; k3k3+1
for i=p,u
a
i
b
i

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:
t
0
(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=2
k
. Atunci:
T(n) = T(2
k
) =2 T(2
k-1
) + a 2
k
=
=2[2T(2
k-2
) + a 2
k-1
] + a 2
k
= 2
2
T(2
k-2
) + 2 a 2
k
=
=2
2
[T(2
k-3
) + a 2
k-2
] + 2 a 2
k
= 2
3
T(2
k-3
) + 3 a 2
k
=
. . .
= 2
i
T(2
k-i
) + i
.
a
.
2
k
=
. . .
=2
k
T(0) + k a 2
k
= nt
0
+ 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=(a
1
,...,a
n
). 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 (a
p
,...,a
u
) secvena curent care trebuie sortat. Vom poziiona pe
a
p
n secvena (a
p
,...,a
u
), adic printr-o permutare a elementelor secvenei
x=a
p
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 a
p
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 a
p
n cadrul secvenei (a
p
,...,a
u
).
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 a
i
<a
j

then
else a
i
a
j
; (ii,jj) (-ii,-jj)
ii+ii; jj+jj (*)
poz i
end

S urmrim cum decurg calculele pentru secvena:
(a
4
,...,a
11
)=(6,3,2,5,8,1,9,7)
se compar 6 cu a
11
,a
10
,... pn cnd gsim un element mai mic. Acesta
este a
9
=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 a
8
=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 a
1
cu a
2
,...,a
n
rezultnd
c el se afl pe poziia final, apoi se compar a
2
cu a
3
,...,a
n
rezultnd c el se
afl pe poziia final etc. Timpul n acest caz este de ordinul O(n
2
).

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:

= =
+ + =
=
0 T(0) T(1)
k)] T(n 1) [T(k
n
1
1 n T(n)
n
1 k
66 6. METODA DIVIDE ET IMPERA


deoarece:
n cazul cel mai defavorabil a
1
se compar cu celelalte n-1 elemente;
a
1
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):


|

\
|
+ =
|

\
|

\
|

+
+

=
+
+

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



Prin adunarea relaiilor de mai sus, obinem:
1
1 n
2
3
1
...
n
1
1 n
1
2
1 n
T(n)

+
+
|

\
|
+ + +
+
=
+

Cum suma ultimilor doi termeni este negativ, rezult:
1 n
2
1 n
2
| 2lnx dx
x
1
1 n
T(n)
+
+

=
+
2 2 ln(n+1)
(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.
2 3
n n+1
f(x)=ln x





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:
A
x
A : mulimea elementelor din A de a cror valoare depinde v(x);
f
x

:
funcie care specific dependena de mai sus. Dac
A
x
={a
1
,...,a
k
}, atunci v(x)=f
x
(v(a
1
),...,v(a
k
)).
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};
A
3
={1,2}; A
4
={1,2,3}; A
5
={1,4};
A
11
={7,8}; A
12
={9,10}; A
13
={11,12}.
Elementele din X au asociat valoarea 1.
Fiecare funcie f
x
calculeaz v(x) ca fiind suma valorilor elementelor din
A
x
. 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 A
x
. Vrfurile din X apar subliniate.
7
68 7. METODA PROGRAMRII DINAMICE













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.






Observaii:
- A poate fi chiar infinit;
- B este de obicei N, Z, R, {0,1} sau un produs cartezian;
- f
x
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 O
x
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) O
z
nu are circuite;
2) vrfurile din O
z
n care nu sosesc arce fac parte din X.

Prezentm n continuare mai multe metode/ncercri de rezolvare a
problemei enunate.




1
3
4
2
3
13
11
5
4
2
1
6
12
7 8 9 10
7.2. Metoda irului cresctor de mulimi 69


7.2. Metoda irului cresctor de mulimi

Fie A o mulime finit i X o submulime a sa. Definim urmtorul ir
cresctor de mulimi:

X
0
= X
X
k+1
= X
k
{x AA
x
X
k
}, k>0
Evident, X
0
X
1
... X
k
X
k+1
... A.

Propoziie. Dac X
k+1
=X
k
, atunci X
k+i
=X
k
,iN.
Facem demonstraia prin inducie dup i.
Pentru i=1 rezultatul este evident.
Presupunem X
k+i
=X
k
i demonstrm c X
k+i+1
=X
k
:
X
k+i+1
= cf. definiiei irului de mulimi
= X
k+i
{x A A
x
X
k+i
} = cf. ipotezei de inducie
= X
k
{x A A
x
X
k
} = cf. definiiei irului de mulimi
= X
k+1
= cf. ipotezei
= X
k
.

Consecine.
- ne oprim cu construcia irului cresctor de mulimi la primul k cu X
k
=X
k+1

(A este finit!);
- dac aplicm cele de mai sus pentru problema general enunat, aceasta
are soluie dac i numai dac zX
k
.

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 A
x
U
then U U {x}; V V\{x}
calculeaz v(x) conform funciei f
x

if x=z
then write v(x); stop
until V=W { nu s-a avansat! }
write(z, 'nu este accesibil)

70 7. METODA PROGRAMRII DINAMICE


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:
S
i
= lista succesorilor lui i;
nrpred
i
= numrul predecesorilor lui i din mulimea M curent.
7.3. Sortarea topologic 71


Etapa de iniializare const n urmtoarele:

S
i
, nrpred
i
0, i
C ; nr 0 { nr este numrul elementelor produse la ieire }
for k=1,m { m este numrul perechilor din relaia "<" }
read(i,j)
S
i
j; nrpred
j
nrpred
j
+1
for i=1,n
if nrpred
i
=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 f
i

if i=z
then write(i,v(i)); stop
for toi jS
i

nrpred
j
nrpred
j
-1
if nrpred
j
=0 then j C
if nr<n then write('Nu')

Fiecare executare a corpului lui while necesit un timp proporional cu
S
i
. Dar |S
1
|+...+|S
n
|=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 yA
x
\X
DivImp(y)
calculeaz v(x) conform funciei f
x

end;
72 7. METODA PROGRAMRII DINAMICE



Apare un avantaj: sunt parcurse doar vrfurile din O
z
. 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 G
z
= subgraful asociat lui O
z
;
- aplicm sortarea topologic.
Fie G
z
=(X
z
,M
z
). Iniial X
z
=, M
z
=.
Pentru a obine graful G
z
executm apelul DF(z), unde procedura DF este:

procedure DF(x)
x X
z

for toi yA
x

if yX
z
then (y,x) M
z
; DF(y)
end;

Timpul este liniar.

Observaie. Ar fi totui mai bine dac :
- am cunoate de la nceput G
z
;
- 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, xO
z
(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.









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 jA
x
cu parcurs(j)=false
postord(j)
calculeaz v(x) conform funciei f
x
; 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.
3
5
2 1
3
4
5
4
2 1
74 7. METODA PROGRAMRII DINAMICE



Mai pe scurt, putem afirma c:





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:
F
0
=0; F
1
=1;
F
n
= F
n-1
+ F
n-2
, n2
Dorim s calculm F
n
pentru un n oarecare.

Aici A={0,...,n}, X={0,1}, B=N, iar
A
k
={k-1,k-2}, k2
v(k)=F
k
; f
k
(a,b)=a+b, k2
Un prim graf de dependene este urmtorul:





S observm c o mai bun alegere a mulimii B simplific structura PD-
arborelui.

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



i obinem algoritmul binecunoscut:

a0; b1
for i=2,n
(a,b)(b,a+b)
write(b)
Metoda programrii dinamice const n identificarea
unui PD-arbore i parcurgerea sa n postordine.
. . . .
2
3
0 1
n-2 n-1 n=z
n n-1 3
2
1
7.6. Metoda programrii dinamice 75


Exemplul 2. Calculul sumei a
1
+ ...+a
n


Este evident c trebuie calculate anumite sume pariale.
O prim posibilitate este s considerm un graf n care fiecare vrf s fie o
submulime {i
1
,...,i
k
} a lui {1,2,...,n}, cu valoarea asociat
1
i
a +
2
i
a +...+
k
i
a . 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 s
i,j
=a
i
+...+a
j
. Vom nota un
astfel de vrf prin (i:j). Dorim s calculm valoarea a
1
+...+a
n
vrfului
z=(1:n). Putem considera mai muli PD-arbori:

Arborele liniar constituit din vrfurile cu i=1. Obinem relaiile de recuren:
s
1,1
=a
1
;
s
1,j
=s
1,j-1
+a
j
, j=2,3,...,n
care corespund asociativitii la stnga: (...((a
1
+a
2
)+a
3
)+...).

Arborele liniar constituit din vrfurile cu j=n. Acest arbore corespunde
asociativitii la dreapta a sumei:
s
n,n
=a
n
s
i,n
=a
i
+s
i-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:













Relaiile de recuren sunt:
s
ii
=a
i
s
i,j
=s
ik
+s
k+1,j
pentru i<j.
(1:7)
(1:4) (5:7)

(1:2)

(3:4) (5:6)
(7:7) (1:1) (2:2) (3:3) (4:4) (5:5) (6:6)
76 7. METODA PROGRAMRII DINAMICE


iar algoritmul const n parcurgerea pe niveluri, de jos n sus, a arborelui; nu este
folosit vreun tablou suplimentar:

k1
while k<n
k2k+k; i1
while i+kn
a
i
a
i
+a
i+k
; ii+k2
k k2

Rezultatul este obinut n a
1
. Evoluia calculelor apare n urmtorul tabel:

n k2 k i
7 2 1 1
a
1
a
1
+a
2

3
a
3
a
3
+a
4

5
a
5
a
5
+a
6

7
4 2 1
a
1
a
1
+a
3

5
a
5
a
5
+a
7

9
8 4 1
a
1
a
1
+a
5

9

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=(a
1
,...,a
n
). 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 a
i.

A={1,2,...,n}; X={n};
A
i
={i+1,...,n} i f
i
=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 & a
i
<a
j
}
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)a
i
; scrie(i)

unde procedura scrie are forma:

procedure scrie(i)
if ind=nr
then write(s)
else for j=i+1,n
if a
i
<a
j
& 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 A
1
A
2
...A
n
, unde dimensiunile
matricilor sunt respectiv (d
1
,d
2
),(d
2
,d
3
),....,(d
n
,d
n+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 A
1
A
2
A
3
A
4
unde A
1
(100,1), A
2
(1,100), A
3
(100,1),
A
4
(1,100).

Pentru ordinea de nmulire (A
1
A
2
)(A
3
A
4
) sunt necesare 1.020.000 de
nmuliri elementare. n schimb, pentru ordinea de nmulire (A
1
(A
2
A
3
))A
4

sunt necesare doar 10.200 de nmuliri elementare.

78 7. METODA PROGRAMRII DINAMICE


Fie cost(i,j) numrul minim de nmuliri elementare pentru calculul
produsului A
i
...A
j
. 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)+d
i
d
k+1
d
j+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.












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)

i
j
(i,j)
n
j
i
1
(j,j)
(i,i)
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
2 j
3
2
2) 1)(j (j
n
2 j
1 j
1 i
) O(n 1) j(j 1) i (j

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 a
ij
= numrul minim de ptrate n care poate fi descompus un
dreptunghi de laturi i i j. Evident a
ij
=a
ji
. Rezultatul cutat este a
mn
.
Vrfurile grafului de dependene sunt (i,j), iar valorile asociate sunt a
ij
.









Pentru calculul lui a
ij
avem de ales ntre a face:
- o tietur pe vertical; costurile sunt: a
ik
+a
i,j-k
, k j/2 ;
- o tietur pe orizontal; costurile sunt: a
k,j
+a
i-k,j
, k i/2 .
Rezult c valoarea a
ij
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-k
k
k
i-k
i
j
j
i
(i,j)
80 7. METODA PROGRAMRII DINAMICE


Dependenele pot fi exprimate astfel:
a
i,1
=i, i=1,...,m
a
1,j
=j, j=1,...,n
a
ii
=1, =1,...,m
a
ij
= min{,}, unde
=min{a
ik
+a
i,j-k
| k j/2} , iar =min{a
k,j
+a
i-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 a
ij
conform celei de a patra dependene de mai sus
if jm then a
ji
a
ij


Observaie. Am lucrat numai pe partea superior triunghiular, cu
actualizri dedesubt.





METODA BRANCH AND BOUND



8.1. 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 2 3 4 1 2 3 4
5 7 8 5 6 7 8
9 6 10 11 9 10 11 12
13 14 15 12 13 14 15

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.

8
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:






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

=
6 2 6
3 8 4
9 1 5
2 7 3
C
8.1. Prezentare general 83





















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
(3,2) (2,3) (4,2)
(4,3)
(2,4) (4,5) (3,4)
(4,2) (3,4) (3,2) (2,4) (2,3)
(1,4) (1,3)
(1,2
)
1
2 3 4
5 6 7 8 9 10
11 12 13 14 15 16
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 min-
ansamblu: 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;
min {c(y) | y fiu al lui x } dac x nu este vrf final.
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 i
final
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); i
final
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 i
final

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:
lungimea circuitului corespunztor lui x dac x este frunz
min {c(y) | y fiu al lui x } altfel.

Fiecrui vrf x i vom ataa o matrice de costuri M
x
(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;
n caz contrar, plecnd de la M
x
i (x) procedm astfel:
- elementele liniei i devin , deoarece mergem sigur ctre
vrful j din graf;
- elementele coloanei j devin , deoarece am ajuns sigur n
vrful j din graf;
- M
x
(j,1) , pentru a nu reveni prematur n rdcina 1;
- reducem noua matrice M
x
i obinem M
y
; fie r cantitatea cu
care s-a redus M
x
. Vom lua (y) (x)+r+M
x
(i,j).
(i,j)
y
x
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

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

Pentru vrful 2:
- plecm de la M
1
i punem pe linia 1 i coloana 2;
- elementul de pe linia 2 i coloana 1 devine ;
- reducem linia 3 cu 3;
- n acest mod obinem (2)=9+3+1=13

Pentru vrful 3:
- plecm de la M
1
i punem pe linia 1 i coloana 3;
- elementul de pe linia 3 i coloana 1 devine ;
- reducem linia 2 cu 3;
- n acest mod obinem (3)=9+3+5=17

Pentru vrful 4:
- plecm de la M
1
i punem pe linia 1 i coloana 4;
- elementul de pe linia 4 i coloana 1 devine ;
- nu este necesar vreo reducere;
- n acest mod obinem (4)=9+0+0=9

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

Pentru vrful 9:
- plecm de la M
4
i punem pe linia 4 i coloana 2;
- elementul de pe linia 2 i coloana 1 devine ;
- nu este necesar vreo reducere;
- n acest mod obinem (9)=9+0+0=9

Pentru vrful 10:
- plecm de la M
4
i punem pe linia 4 i coloana 3;
- elementul de pe linia 3 i coloana 1 devine ;
- reducem linia 2 cu 3, iar linia 3 cu 5;
- n acest mod obinem (10)=9+8+4=21

=
4 0 3
0 5 0
8 0 3
0 5 1
M1





=
1 0
0 0
8 0
M2





=
0 3
0 5
5 0
M3





=
4 0
5 0
0 3
M4





=
0
0
M10





=
0
0
M9
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:

=
=
2 k A, A A
A A
1 - k k
1

a crui semnificaie este urmtoarea:

Propoziia 1. A
k
(i,j) = numrul drumurilor de lungime k de la i la j.
- pentru k=1: evident.
- k-1 k : =
=

n
1 s
1 k k
j) A(s, s) (i, A j) (i, A , unde s este penultimul vrf din
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:

=
=
2 k A, A A
A A
1) - (k (k)
(1)
o

unde j) (s, A s) (i, A j) (i, A
1) (k 1) (k
n
1 s
(k)
=

=
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(n
4
).
9
90 9. DRUMURI N GRAFURI


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.
Considerm

+
=
> < > <
=
altfel
dac
dac
j i 0
M j i, ) j i, et(
j) P(i,
i irul de matrici:
{

+ =
=

1 k j) (k, P k) (i, P j), (i, P j) (i, P
P P
1 k 1 k 1 k k
0
}, min


Propoziia 3. P
n
este matricea celor mai scurte drumuri.
Vom demonstra prin inducie dup k urmtoarea afirmaie:
P
k
(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, P
k
(i,j)=P
k-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 P
k
(i,j)=P
k-1
(i,k)+P
k-1
(k,j).


Observaii:
1) s-a folosit metoda programrii dinamice;
2) P
k
(i,i)=0;
3) P
k
(i,k)=P
k-1
(i,k) i P
k
(k,j)=P
k-1
(k,j), deci la trecerea de la P
k-1
la
P
k
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(n
3
).

i
k
j
9. DRUMURI N GRAFURI 91


Dac dorim s determinm doar existena drumurilor i nu lungimea lor
minim, vom proceda similar. Considerm irul de matrici:

=
=

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


Propoziia 4. A
n
este matricea drumurilor.
Demonstrm prin inducie dup k urmtoarea afirmaie:
A
k
(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 A
k
(i,j)=1, atunci fie A
k-1
(i,j)=1, fie A
k-1
(i,k)=A
k-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(n
3
).

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

fixat. Este de ateptat ca timpul de executare s scad.
Mai precis, cutm d(x) = lungimea drumului minim de la x
0
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 x
0
.

Pentru regsirea drumurilor vom folosi vectorul tata.
Perechiile (d(x),tata(x)) sunt iniializate astfel:
- (0,0) pentru x=x
0
;
- (et(<x
0
,x>),x
0
) dac <x
0
,x>M;
- (+,0) altfel.
92 9. DRUMURI N GRAFURI


Fie T = mulimea vrfurilor x pentru care d(x) are valoarea final.
n continuare, algoritmul lucreaz astfel:

T {x
0
}
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 x
0
la x;
2) xT : d(x) = lungimea celui mai scurt drum de la x
0
la x, ce trece
numai prin vrfuri din T.

Pentru |T|=1, concluzia este evident.
|T| |T|+1: Fie x' vrful nou adugat.
Demonstrm cele dou afirmaii de mai sus:
1) d(x) este cel final:
Presupunem prin absurd c exist un drum de la x
0
la x de lungime mai
mic dect d(x). Acest drum trebuie s treac printr-un vrf 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(n
2
).
2) Pe baza vectorului tata, putem regsi pentru orice xV drumul minim ce
l leag de x
0
n timp liniar. Regsirea tuturor acestor drumuri necesit un
timp de ordinul O(n
2
), deci complexitatea n timp a algoritmului nu
crete.
3) Dac dorim s aflm numai drumul minim de la x
0
la un vrf x
1
dat, ne
oprim cnd x=x
1
; 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.

x
0
yT
x'
x'
T
x
0
x

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