Algoritmul lui Roy-Floyd
Fie G=(V, E) un graf neorientat, unde V are n elemente (n noduri) si E are m elemente (m muchii) memorat prin matricea ponderilor. Se cere ca pentru doua noduri x,y citite sa se determine lungimea minima a lantului de la x la y.
Astfel:
Initial matricea ponderilor pentru nodurile 1 si 4 va retine 10. Se observa ca lantul 1,2,3,4 determina o suma a costurilor mai mica: 2+3+1=6. Lungime minima a lantului de la 1 la 4 este 6.
Algoritmul:
-se genereaza matricea ponderilor:
0 2 pinf 10 pinf
2 0 3 pinf pinf
pinf 3 0 1 8
10 pinf 1 0 pinf
pinf pinf 8 pinf 0
Unde pinf reprezinta plus infinit
-se incearca pentru oricare pereche de noduri i,j sa se obtina “drumuri” mai scurte prin noduri intermediare k (kÎ1…n).
Acest lucru se determina comparand “lungimea” lantului a[i,j] cu lungimea lantului care trece prin k si daca:
a[i,j] > a[i,k]+a[k,j] atunci se atribuie: a[i,j] ¬ a[i,k]+a[k,j]
Astfel generarea matricii drumurilor optime se realizeaza cu urmatoarea secventa:
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j]>a[i][k]+a[k][j])
a[i][j]=a[i][k]+a[k][j];
Se obtine:
0 2 5 6 13
2 0 3 4 11
5 3 0 1 8
6 4 1 0 9
13 11 8 9 0
In continuare, dupa determinarea matricii lanturilor optime, pentru doua noduri citite x, y se cere sa se reconstituie un lant optim de la x la y (pot fi mai multe solutii).
Solutie:
-se determina daca exista un lant de la x la y (ar putea sa nu existe un astfel de lant daca graful nu este conex):
cand a[x,y] ¹¥
-se descompune “drumul” de la x la y prin k atunci cand: a[x][y]=a[x][k]+a[k][y];
- pentru un astfel de algoritm se utilizeaza strategia Divide et Impera
Iata o solutie:
#include<fstream.h>
#include<conio.h>
const pinf=1000; //pentru plus infinit
int a[20][20],n,m;
void citire_cost()
{fstream f;
int i,j,x,y,c;
f.open("roy.in",ios::in);
if(f)
cout<<"deschiderea a reusit";
else
cout<<"eroare la deschidere!";
cout<<endl;
f>>n>>m;
//initializare matrice
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i==j)
a[i][j]=0;
else
a[i][j]=pinf;
for(i=1;i<=m;i++)
{f>>x>>y>>c;
a[x][y]=a[y][x]=c;}
}
void afisare_mat()
{for(int i=1;i<=n;i++)
{for(int j=1;j<=n;j++)
if(a[i][j]==pinf)
cout<<"pinf ";
else
cout<<a[i][j]<<" ";
cout<<endl;}
}
void genarare_matrice_drumuri_optime()
{for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j]>a[i][k]+a[k][j])
a[i][j]=a[i][k]+a[k][j];
}
void descompun_drum(int i,int j) //realizeaza descompunerea portiunii de la i la j prin k
{int g=0,k=1;
while(k<=n&&!g)
{if(i!=k&&j!=k)
if(a[i][j]==a[i][k]+a[k][j])
{descompun_drum(i,k);
descompun_drum(k,j);
g=1;} //g marcheaza daca se poate realiza descompunerea
k++;
}
if(!g)
cout<<j<<" "; //cand “drumul” nu mai poate fi descompus afisez extremitatea finala
}
void scriu_drum(int nodini,int nodfin) // functia primeste ca parametri cele doua noduri pt care se determina optimul
{if(a[nodini][nodfin]<pinf)
{cout<<"lantul de la "<<nodini<<" la "<<nodfin<<" are lungimea "<<a[nodini][nodfin];
cout<<endl<<"un drum optim este: "<<endl;
cout<<nodini<<" ";
descompun_drum(nodini,nodfin); // apeleaza functia care afiseaza efectiv lantul
}
else
cout<<"nu exista drum de la "<<nodini<<" la "<<nodfin;
}
void main()
{clrscr();int x,y;
citire_cost();
cout<<endl<<"matricea ponderilor "<<endl;
afisare_mat();
genarare_matrice_drumuri_optime();
cout<<endl<<"matricea drumurilor optime "<<endl;
afisare_mat();
cout<<endl<<"Se determina drumul minim intre varfurile x si y "<<endl;
cout<<"x=";
cin>>x;
cout<<"y=";
cin>>y;
scriu_drum(x,y);
getch();
}