Sunteți pe pagina 1din 11

Arborele parial de cost minim

Definiie: Se numete arbore un graf neorientat, conex i fr cicluri.



n figura alturat este desenat un arbore. Se observ c oricum am elimina o muchie, graful i
pierde proprietatea de conexitate, i oriunde am aduga o muchie, apare un ciclu. Acest lucru este valabil
n orice arbore.

Teorem:
Fie un graf neorientat G=(X,U).
Urmtoarele afirmaii sunt echivalente:
1) G este un arbore
2) G este un graf conex, minimal cu
aceast proprietate (eliminnd o muchie
oarecare se obine un graf neconex)
3) G este un graf fr cicluri,
maximal cu aceast proprietate (dac se
adaug o muchie se obine un graf care
are mcar un ciclu)

Definiie: Fie graful G=(X,U) cu n>2 noduri, m muchii i p componente conexe. Numrul v(G)=m-n+p
se numete numrul ciclomatic al grafului G.

Observaii:
- se poate arta c v(G) furnizeaz numrul de cicluri elementare din graf
- numrul v(G) reprezint numrul de muchii ce trebuie nlturate din graf astfel nct acesta s
nu conin cicluri

Definiie: Fie G un graf neorientat. Un graf parial H al lui G, cu proprietatea c H este arbore, se
numete arbore parial al lui G.

Corolar: Un graf neorientat G conine un arbore parial dac i numai dac G este conex.

Propoziii:
1) Un arbore cu n>2 vrfuri conine cel puin dou vrfuri terminale.
2) Orice arbore cu n vrfuri are n-1 muchii.
3) Un graf G cu n vrfuri i m muchii este arbore dac este aciclic i m=n-1.
4) Un graf G cu n vrfuri i m muchii este arbore dac este conex i m=n-1.
5) Un graf cu n vrfuri i cel puin n muchii conine cel puin un ciclu.
6) Numerele d1>d2>d3>.......>dn>1 sunt gradele nodurilor unui arbore cu n>2 noduri dac i
numai dac d1+d2+....+dn=2(n-1).

Definiie: Un graf neorientat care nu conine cicluri se numete pdure.

n practic se ntlnesc foarte des probleme de tipul urmtor: se dorete conectarea unor
consumatori la o surs de energie electric astfel nct costul branrii s fie minim. Transpunnd
problema n termenii teoriei grafurilor, se cere de fapt determinarea unui arbore parial de cost minim,
adic un arbore care are proprietatea c suma costurilor muchiilor sale s fie minim.

Definiie: Suma costurilor muchiilor unui graf se numete costul grafului. Dac se definete funcia
c:UR
+
care asociaz fiecrei muchii un numr real numit cost, costul grafului este

e
=
U u
u c G c ) ( ) (
Funcia c se numete funcia cost.
Fie G=(X,U) un graf conex, reprezentat prin matricea costurilor. Se tie c prin eliminarea
uneia sau a mai multor muchii se obine un graf parial. Dac graful parial al unui graf G conex este
arbore, acesta se numete arbore parial al lui G. Dac dintr-un graf conex G=(X,U) se elimin
muchii astfel nct s se obin un arbore parial al crui cost s fie minim, acesta se numete arbore
parial de cost minim(APM).

Proprietate: Pentru graful G conex, cu funcia de cost c, exist un graf parial H conex i de cost minim,
care este i arbore.
Pentru determinarea APM sunt cunoscui mai muli algoritmi, cei mai utilizai fiind algoritmul lui
Kruskal (1956) i algoritmul lui Prim, ambii bazai pe o strategie Greedy.


Algoritmul lui Kruskal

Se pleac iniial de la n arbori disjunci, fiecare fiind format dintr-un nod al grafului : H
1
,
H
2
,.,H
n
. La fiecare pas vom ncerca s unificm doi dintre arborii existeni, alegerea celor doi arbori
ce vor fi unificai fcndu-se astfel: dintre toate muchiile nealese nc, se selecteaz muchia de cost
minim care are o extremitate ntr-un arbore i cealalt extremitate n alt arbore. Prin adugarea acestei
muchii la arborele care se construiete, se vor unifica cei doi arbori disjunci ntr-unul singur. Dup n-1
pai se obine APM care conine n-1 muchii.
Algoritmul pseudocod corespunzator este:

algoritm Kruskal(G,U)
AC
pentru fiecare varf ve X(G) executa
Formeaza_Multime(v)
sfarsit pentru
sorteaza muchiile din u in ordinea crescatoare a costului c
pentru fiecare muchie (u,v)eU(G),in ordinea crescatoare a costului
executa
daca Gaseste_Multime(u)=Gaseste_Multime(v) atunci
AA {(u,v)}
Uneste(u,v)
sfarsit daca
sfarsit pentru
returneaza A

Algoritmul folosete o structur de date pentru mulimi disjuncte pentru reprezentarea mai multor mulimi
de elemente disjuncte. Fiecare mulime conine vrfurile unui arbore din pdurea curent. Funcia
Gaseste_Multime(u) returneaz un element reprezentativ din mulimea care l conine pe u. Astfel,
putem determina dac dou vrfuri u i v aparin aceluiai arbore testnd dac Gaseste_Multime(u)
este egal cu Gaseste_Multime(v). Combinarea arborilor este realizat de funcia Uneste(u,v).

Pentru a implementa algoritmul lui Kruskal vom reprezenta graful prin vectorul muchiilor,
fiecare muchie avnd ataat i costul. Pentru a specifica la fiecare pas din ce arbore face parte un nod i,
vom folosi vectorul L. Iniial, pornim cu n arbori disjunci, deci L[i]=i , pentru ie{1,2,.n}. Pentru a
eficientiza alegerea muchiilor, vectorul muchiilor u se va ordona cresctor dup costul muchiilor.
Pentru a alege cele n-1 muchii ale APM se parcurg elementele vectorului u astfel:
Fie v=[u[i].x,u[i].y] muchia ce urmeaz a fi analizat (plecm cu i=1). Dac n vectorul L
extremitile muchiilor au valori egale, adic L[u[i].x]=L[u[i].y], atunci cele dou extremiti
aparin aceluiai subarbore, deci alegerea acestei muchii ar duce la formarea unui ciclu. n caz contrar,
nseamn c extremitile muchiei fac parte din subarbori diferii, fie aceatia H
x
i H
y
, care pot fi unificai,
operaie care presupune c pentru toate vrfurile celor doi arbori trebuie s apar n vectorul L aceeai
valoare (provenit din primul sau din al doilea arbore). Acest pas se repet pn am reuit s alegem
cele n-1 muchii ale APM.

Exemplu: Fie graful din figura urmtoare:







Pasii algoritmului sunt:

Configuratia initiala:

Dup ordonarea
cresctoare a muchiilor
dup costul c ataat,
avem:



u=([5,4],[3,4],[3,5],[1,2],
[2,5],[2,3],[6,5],[2,6],[2,7],
[1,7],[7,6])
c=(1,1,2,2,2,3,3,3,3,4,5)
L=(1,2,3,4,5,6,7) , fiecare nod fcnd parte dintr-un arbore.


















Pasul 1:

Se alege muchia de cost minim [5,4]
i L devine: (1,2,3,5,5,6,7)
deoarece am unificat arborii H
4
i H
5
i
am obinut subarborele H
5
=(4,5).
Ceilali subarbori rmn nemodificai.









Pasul 2:
Se alege muchia [3,4]
de cost minim, unificm H
3
i H
5
i
obinem L=(1,2,3,3,3,6,7) i
H
3
=(3,4,5).
















Pasul 3:
Se verific muchia [3,5] care nu poate fi
aleas deoarece L[3]=L[5] (vrfurile 3 i 5
aparin deja aceluiai subarbore H
3
) i alegerea ei
ar provoca apariia unui ciclu.
Se alege muchia [1,2], se unific H
1
i
H
2
i obinem: L=(1,1,3,3,3,6,7) i
H
1
=(1,2).









Pasul 4:
Se alege muchia [2,5], se unific H
1
i H
3
i obinem: L=(1,1,1,1,1,6,7) i
H
1
=(1,2,3,4,5).











Pasul 5:

Muchia [2,3] nu poate fi aleas pentru c ar
crea un ciclu.
Se alege muchia [6,5] i se obine subarborele
H
1
=(1,2,3,4,5,6).












Pasul 6:
Se alege muchia [2,7] si L devine (2,2,2,2,2,2,2), ceea ce corespunde unui arbore parial
de cost minim H=([1,2], [2,5], [3,4], [5,4], [6,5], [2,7]), costul total fiind 12.

















Nu are importan care subarbore se alege pentru a transfera vrfurile celuilalt subarbore.

Observaie: Dac exist mai multe muchii cu acelai cost, pentru un graf conex G pot exista mai multe
posibiliti de alegere a unei muchii de cost minim, deci pot exista mai muli APM. Aceti arbori se vor
deosebi prin muchiile ce vor fi luate n consideraie, i nu prin costul asociat, deoarece aceast cost va fi
acelai pentru toi arborii, i anume ei vor avea cost minim.

Implementarea algoritmului lui Kruskal este:

#include<iostream>
#include<fstream>
Using namespace std;
#define N 30
#define M 60
typedef struct {
int x,y;
float cost;
}MUCHIE;
void citire_muchii(MUCHIE u[M],int &n,int &m)
{
int k;
ifstream f(graf.in);
cin>>n>>m;
for(k=1;k<=m;k++)
cin>>u[k].x>>u[k].y>>u[k].cost;
f.close();
}
void sortare(MUCHIE u[M],int m)
{
MUCHIE aux; int i,j;
for(i=1;i<=m-1;i++)
for(j=i+1;j<=m;j++)
if(u[i].cost>u[j].cost)
{
aux=u[i]; u[i]=u[j]; u[j]=aux;
}
}
void creare_apm(MUCHIE u[M],int n,int m)
{
int L[N],k,i,v,w,j;
float ct=0; //cost total apm
for(i=1;i<=n;i++) L[i]=i; //n subarbori disjuncti
i=1; k=0;
cout<<endl<<APM: ";
while(k<n-1)
{
if(L[u[i].x]!=L[u[i].y])
//extremitatile muchiei sunt in subarbori diferiti
{
k++;
ct+=u[i].cost; //adaugam costul muchiei i
cout<<u[i].x<<u[i].y;
v=L[u[i].y]; w=L[u[i].x];
for(j=1;j<=n;j++)
if(L[j]==v) L[j]=w; //reunim cei doi arbori
}
i++; //trecem la urmatoarea muchie
}
cout<<endl<<ncostul total este<<ct;
}
int main()
{
MUCHIE u[M]; int n,m;
citire_muchii(u,n,m); sortare(u,m); creare_apm(u,n,m);
}


Algoritmul lui Prim


Graful conex este dat prin matricea costurilor, forma 1. La fiecare pas k>0 obinem un arbore
H
1
cu k+1 vrfuri i n-(k+1) arbori cu cte un singur vrf. La fiecare pas se alege muchia de cost
minim care are o extremitate n arborele H
1
deja creat i cealalt extremitate liber. Lucrm cu vectorul T
n care vom avea, pentru fiecare vrf neales nc, vrful din H
1
de care acesta se leag printr-o muchie
de cost minim (legtur de tip tat). n componenta corespunztoare din vectorul Q vom avea costul
muchiei adugate. Cum la nceput avem n H
1
doar vrful 1, n toate componentele lui T avem 1, cu
excepia lui T[1], iar n Q, valorile corespunztoare din linia 1 a matricei costurilor c. La pasul k, dup
alegerea unui nou vrf w care se adaug la H
1
, se vor actualiza componentele din T i Q pentru vrfurile
nealese nc deoarece adugarea vrfului w poate modifica aceste valori. Algoritmul are ordinul de
complexitate u(n
2
).
Algoritmul pseudocod corespunztor este:

algoritm Prim(G,c,rad)
QX(G)
pentru fiecare ueQ executa
D[u]
sfarsit pentru
D[rad]0
T[rad]0
cat timp Q=0 executa
uExtrage_Minim(Q)
pentru fiecare vecinilor lui u executa
daca veQ i c(u,v)<D[v] atunci
T[v]u
D[v]c(u,v)
sfarsit daca
sfarsit pentru
sfarsit cat timp

Se iniializeaz vectorul Q astfel nct acesta s conin toate vrfurile grafului i se iniializeaz cmpul D
al fiecrui vrf cu , excepie fcnd rdcina rad, al crei cmp D este iniializat cu 0. Tatl rdcinii se
iniializeaz cu 0, deoarece rad nu are nici un printe. Pe parcursul algoritmului, mulimea X-Q conine
vrfurile arborelui curent. Se identific un vrf ueQ incident unei muchii de cost minim care traverseaz
tietura (X-Q,X) (cu excepia primei iteraii n care u=rad deoarece are cheia D[rad]=0). Eliminarea
lui u din mulimea Q l adaug pe acesta mulimii U-Q a vrfurilor din arbore. n liniile urmtoare se
actualizeaz cmpurile D i T ale fiecrui vrf v adiacent lui u, dar care nu se afl n arbore. Actualizarea
respect condiiile D[v]=c(v,T[v]) i (v,T[v]) s fie o muchie de cost minim care l unete pe v cu
un vrf din arbore.

Fie graful din figura
urmtoare:













Configuraia iniial:




Pasul 1:


Pasul 2:




















Pasul 3:




Pasul 4:



Pasul 5:





Pasul 6:




Implementarea algoritmului lui Prim este:

#include<iostream>
using namespace std;
#define N 30
#define M 60
#define INF 1<<14
void citire_graf(int c[N][N],int &n)
{
int m,i,j,x,y,z;
ifstream f(graf.in);
cin>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) c[i][j]=INF;
for(i=1;i<=n;i++) c[i][i]=0;
for(i=1;i<=m;i++)
{
cin>>x>>y>>z;
c[x][y]=c[y][x]=z;
}
f.close();
}
void creare_apm(int c[N][N],int n)
{
int V[N],T[N],Q[N],i,j,min,w,ct=0; //costul total al arborelui
for(i=1;i<=n;i++) V[i]=i; //varfurile neincluse in arbore
V[1]=0;
for(j=2;j<=n;j++)
{
T[j]=1; Q[j]=c[1][j];
}
cout<<endl<<APM: ";
while(1)
{
min=INF; //determinam muchia de cost minim
for(i=2;i<=n;i++)
if(V[i] && Q[i]<min)
{
min=Q[i]; w=i;
}
if(min==INF) break;
V[w]=0; //varful w a fost inclus in arbore
cout<<T[w]<<w; //muchia adaugata
ct+=c[T[w]][w]; //actualizam costul arborelui
for(j=2;j<=n;j++)
if(V[j] && Q[j]>c[w][j])
{
T[j]=w; Q[j]=c[w][j];
}
}
cout<<endl<<costul total este<<ct;
}
int main()
{
int c[N][N],n;
citire_graf(c,n); creare_apm(c,n);
}

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