Sunteți pe pagina 1din 30

Partea a III.

Grafuri
III.1.Grafuri – definiţii, reprezentări, parcurgeri
III.2. Conectivitate. Drumuri în graf. Grafuri ponderate. Drumuri
de cost minim
III.3. Grafuri de tip arbore. Arbore partial de cost minim.
Algoritmii Kruskal și Prim
III.4. Aplicații ale parcurgerii grafurilor
III.2. Conectivitate. Drumuri în
graf. Grafuri ponderate. Drumuri
de cost minim
Drumuri în graf

Drumul Γ este proces dacă pentru orice


Orice drum elementar este un proces.
Exemplu
v2

v4
v5

v1 v3

Drum?
Proces?
Elementar?
Drumuri în graf
Matricea existenţei drumurilor
Exemplu

0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1
       
1 0 0 0 2 0 1 1 1 3 1 0 1 1 1 1 1 1
A , A  , A  , M 
1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1
       
1 0 1 0  1 1 1 1 1 1 1 1 1 1 1 1
   
Algoritmul Roy-Warshall
- calculează matricea existenţei drumurilor într-un graf G cu n vârfuri
- Datele de intrare sunt: n, numărul de noduri şi a, matricea de adiacenţă corespunzătoare
grafului
- Matricea m calculată de algoritm constituie ieşirea şi este matricea existenţei drumurilor în
graful G
void Roy_W(int a[][100], int n, int m[][100])
{ int i,j,k;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
m[i][j]=a[i][j];

for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(m[i][j]==0)
for(k=0;k<n;k++)
if(m[i][k]&&m[k][j])
m[i][j]=1;
}
Componente conexe
Componente conexe
Exemplu
1 7 3
2

4 5 8 9 6

Să se determine componenta conexă. V0=1

Observaţie: Calculul componentelor conexe ale unui graf poate fi realizat pe


baza matricei existenţei drumurilor.
Algoritm
V - mulţimea vîrfurilor grafului
m - numărul de muchii
A - matricea de adiacenţă, T – reprezentarea tabelară
M - matricea existenţei drumurilor.
• Algoritmul asociază fiecărui vârf şi fiecărei muchii un indice care identifică
acea componentă conexă din care fac parte. Pentru fiecare vârf v este
calculat vectorul c cu proprietatea că c[v] este indicele componentei
conexe din care face parte .
• Tabelei îi este adăugată o nouă coloană în care, pentru fiecare muchie
este calculat indicele componentei conexe care conţine muchia.
• Pentru fiecare vârf v componenta conexă din care face parte v conţine
toate acele vârfuri u cu proprietatea că M[u-1][v-1]=1 şi muchiile (u,v) .
• Un vârf izolat determină o componentă conexă fără muchii.
Componente conexe
#include <stdio.h>
#include <conio.h>
typedef struct{ int vi,vf;}muchie;

void comp_conexa(int M[][100], int n, int *c, int i, int p, int T[][3], int m)
{ int k;
c[i-1]=p;
for(k=0;k<n;k++)
if((M[i-1][k])&&(c[k]==0))
c[k]=p;
for(k=0;k<m;k++)
if(c[T[k][0]-1]==p)
T[k][2]=p;
}
Componente conexe

//calculul tuturor componentelor conexe


void componente_conexe(int M[][100], int n, int *c,int T[][3], int m, int *ncc)
{ int i,gata,p,v,j;;
for(i=0;i<n;i++)
c[i]=0;
gata=0;v=1;p=1;
while(!gata)
{ comp_conexa(M,n,c,v,p,T,m);
for(j=0;(j<n)&&c[j];j++);
if(j==n)
gata=1;
else
{ v=j+1; p++; }
}
*ncc=p;
}
Drumuri de cost minim
Algoritmul Dijkstra
Este un algoritm care calculeaza distanţele şi drumurile minime de la un nod al
unui graf la toate celelalte noduri din graf
Algoritmul Dijkstra

………………………….
Algoritmul Dijkstra
Algoritmul Dijkstra

#include <stdio.h>
#include <malloc.h>
typedef struct{ float l;
int vf;
}eticheta;

//subprogram
//preia datele unui graf in forma tabelara din fisierul nume si obtine
//matricea ponderilor, unde MAX este valoarea cu semnificatie de infinit
//ultima linie a fisierului contine virful initial din algoritmul Dijkstra

//subprogram
//functia pentru implementarea algoritmului Dijkstra - returneaza
//vectorul de etichete

//subprogram
//functia principala
Preluare graf
void preia_graf(char *nume, float ***w, int *n, int *v0, float MAX)
{ int i,j,m,u,v; float p;
FILE *f=fopen(nume,"rt");
fscanf(f,"%i",n);
float **mw=(float **)malloc(*n*sizeof(float*));
for(i=0;i<*n;i++)
mw[i]=(float *)malloc(*n*sizeof(float));
fscanf(f,"%i",&m);
for(i=0;i<*n;i++)
for(j=0;j<*n;j++)
mw[i][j]=MAX;
for(i=0;i<m;i++)
{ fscanf(f,"%i",&u);
fscanf(f,"%i",&v);
fscanf(f,"%f",&p);
mw[u-1][v-1]=mw[v-1][u-1]=p; }
fscanf(f,"%i",v0);
fclose(f);
*w=mw;}
Implementare alg. Dijkstra

eticheta * Dijkstra (float **w, int n, int v0, float MAX)


{ int i,*prel,nrit,ui,v,vmin;
float lmin;
eticheta *v_et=(eticheta *)malloc(n*sizeof(eticheta));

for(i=0;i<n;i++)
v_et[i].l=MAX;
v_et[v0-1].l=0;

prel=(int*)malloc(n*sizeof(int));
//vector cu proprietatea prel[i]=1 daca pentru virful i+1 a
//fost deja determinat un drum de cost minim
//prel[i]=0 in caz contrar

for(i=0;i<n;i++)
prel[i]=0;
prel[v0-1]=1;
Implementare alg. Dijkstra – cont.

ui=v0;
for(nrit=0;nrit<n-1;nrit++)
{ lmin=MAX;
//sunt recalculate w-distantele de la virfurile v cu prel[v-1]=0 si este determinat vmin,
//urmatorul virf cu proprietatea ca pentru acesta a fost determinat un drum de cost minim,
// lmin
for(v=1;v<=n;v++)
{ if((prel[v-1]==0)&&(v_et[v-1].l>v_et[ui-1].l+w[v-1][ui-1]))
{ v_et[v-1].l=v_et[ui-1].l+w[v-1][ui-1];
v_et[v-1].vf=ui;
}
if((prel[v-1]==0)&&v_et[v-1].l<lmin)
{ lmin=v_et[v-1].l; vmin=v;
}
}
ui=vmin; prel[ui-1]=1;
}
free(prel); return v_et;
}
Functia main()
void main()
{ float **w,MAX=1000000; int n,v0,v,u,i;
char numef[20];
printf("Introduceti numele fisierului care contine graful:");
scanf("%s", numef);
preia_graf(numef,&w, &n, &v0, MAX);
eticheta *rez=Dijkstra(w,n,v0,MAX);
for(v=1;v<=n;v++)
if(v!=v0)
{ printf("Costul unui cel mai ieftin drum de la %i la %i este %8.3f",v,v0,rez[v-1].l);
printf("\n Un drum de cost minim: %i ",v);
u=v;
while(rez[u-1].vf!=v0)
{ printf("%i ",rez[u-1].vf);
u=rez[u-1].vf;
}
printf("%i \n\n",v0);
}
free(rez);
for(i=0;i<n;i++) free(w[i]);
free(w);
}
Algoritmul Roy-Floyd

•  În unele aplicaţii este necesară exclusiv determinarea w - distanţelor D(v0,v),


pentru toţi v din mulțimea V.

• În acest caz algoritmul Roy-Floyd permite o rezolvare a acestei probleme


mai simplu de implementat decât algoritmul Dijkstra.

Pentru (V,E,w) graf ponderat, |V| =n şi W matricea ponderilor, sistemul de w-


distanţe D(v0,v), , poate fi calculat pe baza următorului subprogram (slide-ul
următor),

• Matricea D calculată de algoritm este matricea w-distanţelor D(u,v) în graful


ponderat conex (V,E,w); pentru orice 1<=i, j<=n
Algoritmul Roy-Floyd

void Roy_Floyd (float w[][100],unsigned n,float d[][100],float MAX)


{int i,j,k;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
d[i][j]=w[i][j];

for(j=0;j<n;j++)
for (i=0;i<n;i++)
if(d[i][j]<MAX)
for(k=0;k<n;k++)
if(d[i][k]>d[i][j]+d[j][k])
d[i][k]=d[i][j]+d[j][k];
}
Algoritmul Yen

- Algoritmul propus de Yen pentru calculul tuturor w-distanţelor într-un graf


ponderat este mai eficient din punctul de vedere al volumului de operaţii decât
algoritmul Roy-Floyd.
- Fie (V,E,w) un graf ponderat şi W matricea ponderilor. Pentru determinarea w-
distanţelor de la vârful vk fixat la celelalte vârfuri ale grafului, algoritmul Yen
iniţiază 4 pași (a se vedea slide-ul următor)
 La terminarea algoritmului componentele vectorului B sunt respectiv egale cu
w-distanţa de la vârful vk la orice alt vârf al grafului.
 Într-adevăr, componentele egale cu 1 ale vectorului λ indică, la fiecare reluare a
pasului 3, vârfurile grafului pentru care nu s-a calculat încă w-distanţa la vârful
vk.
 După fiecare efectuare a etapei 3, dacă j0 a fost selectat, atunci B(j0)=D(vk, vj0)
Algoritmul Yen
1
Algoritmul Yen
4
3
5 7
2
2
1
5
4 3
4

Vk=1

J0=2, B(2)=3, = (0,0,0,1,1),


Nicio modificare in matricea D
i=3
1
Algoritmul Yen
4
3
5 7
2
2
1
5
4 3
4

Vk=1

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