sâmbătă, 21 ianuarie 2017

Drumuri minime si maxime

Tags

Drumuri minime si maxime


Considerăm un graf orientat G=(X,U) cu n noduri, în care fiecărui arc îi este asociat un număr întreg numit cost. Semnificaţia acestui cost poate fi foarte variată, în funcţie de domeniul pe care îl descrie graful. De exemplu, dacă graful reprezintă harta unui oraş în care arcele sunt străzile iar nodurile sunt intersecţiile dintre stăyi, atunci putem vorbi despre costul deplasării unui automobil între două intersecţii, de-a lungul unei străzi. Acesta s-ar putea măsura în cantitatea de benzină consumată, calculată prin prisma lungimii străzii în m sau in km.





Pentru evidenţierea costurilor tuturor arcelor unui graf cu n noduri se poate defini o matrice a, cu n linii *n coloane.există două forme ale acestei matrici:
Forma a):  Fiecare element a[i,j] poate fi:
                   -c, dacă există un arc de cost c>0 între nodurile i şi j;
                   -0, dacă i=j;
                   -+¥, dacă nu există arc între nodurile i şi j.
Forma b):   Este absolut similară, cu singura deosebire că în loc de +¥ avem -¥.
Forma a)se foloseşte pentru determinarea drumurilor de cost minim între două noduri, iar forma b) este utilizată în aflarea drumurilor de cost maxim.
Dacă dorim să citim matricea costurilor, evident că nu putem introduce de la tastatură “+¥”! În loc de “+¥ vom da un num[r de la tastatură foarte mare.
Problema determinării drumului minim/ maxim între două noduri face obiectul algoritmului următor.
Aplicaţie 

Algoritmul Roy-Floyd

Se consideră un graf orientat cu n noduri, pentru care se dă matricea costurilor în  forma a). Se cere ca, pentru fiecare pereche de noduri (i, j), să se tipărească costu drumului minim de la i la j.
Plecăm de la următoarea idee: dacă drumul minim între două noduri oarecare i şi j trece printr-un nod k, atunci drumurile de la i la k şi de la k la j sunt la rândul lor minime. Pentru fiecare pereche de noduri (i, j ), cu i, j Î{1,2,…,n}, procedăm astfel:  
·        Dăm lui k pe rând valorile 1,2,…,n, pentru ca nodul k despre care vorbeam mai sus poate fi, cel puţin teoretic, orice nod al grafului. Pentru fiecare k:
Ø dacă suma dintre costul drumului de la i la j şi costul drumului de la k la j este mai mică decât costul drumului de la i la j {a[i, k]+a[k, j]<a[i, j]}, atunci drumul iniţial de la i la j este înlocuit cu drumul indirect i®k®j. această înlocuire fireşte că se va opera ca atare în matrocea costurilor: {a[i, j]:=a[i, k]+a[k, j]}.
Prezentăm în continuare procedura generare care conţine algoritmul descris:
Procedure generare;
var i,j,k:integer;
begin
 for k:=1 to n do
   for i:=1 to n do
       for j:=1 to n do
          if a[i, k]+a[k, j]<a[i, j] then a[i, j]:=a[i, k]+a[k, j];
end;

 



Ø Drumurile minime între toate nodurile se regăsesc la finele algoritmului tot în matricea costurilor, care a suferit n trasformări, pentru k=1,2,…,n.
Ø Unele elemente pot fi +¥, iar pentru simularea lui +¥ am spus că se introduce un număr întreg foarte mare. Prin adunări repetate a două numere întregi foarte mari putem ajunge la un rezultat care depăşeşte cea mai mare valoare posibilă de tipul  integer. De aceea, recomandăm ca elementele matricei costurilor să fie de tipul longint.
Ø În cazul în care problema cerea pentru fiecare pereche de noduri (i, j) costul drumului maxim, modificările necesare ar fi minore:
-         se foloseşte forma b) a matricei costurilor;
-         condiţia  testată în linia if devine “a[i, k]+a[k, j]<a[i, j]”


















program drummax;
uses crt;
type matr=array[1..20,1..20]of integer;
var C,a:matr;
    f:text;
    n:integer;
Procedure citire(var c:matr;var n:integer);
var a:matr;
    i,j:integer;
 Begin
   assign(f,'costgraf.txt');
   reset(f);
   readln(f,n);
   For i:=1 to n do
      For j:=1 to n do
        Read(f,c[i,j]);
   close(f);
 End;
Procedure RF;
var i,j,k:integer;
 Begin
   a:=c;
   For k:=1 to n do
     For i:=1 to n do
       For j:=1 to n do
        If a[i,k]+a[k,j]<a[i,j]
          then a[i,j]:=a[i,k]+a[k,j];
 End;
 Procedure afisare(x:matr;n:integer);
 var i,j:integer;
 Begin
   for i:=1 to n do
   begin
    for j:=1 to n do
     write(x[i,j],' ');
    writeln;
   end;
 end;
 BEGIN
 clrscr;
 citire(c,n);
 afisare(c,n);
 RF;
 afisare(a,n);
 readkey;
 end.





program drummin;
uses crt;
type matr=array[1..20,1..20]of integer;
var c,Dm:matr; {c=matricea costurilor}
    n,i,j:integer;
Procedure citire(var c:matr;var n:integer);
var f:text;
    x,m,i,j:integer;
 Begin
   Assign(f,'cost.txt');
   Reset(f);
   Readln(f,n);
   Readln(f,m);
   for i:=1 to n do
    for j:=1 to n do
      if i=j then c[i,j]:=0
             else c[i,j]:=maxint;
   for i:=2 to m do
    begin
      readln(f,i,j,x); {x=cost}
      c[i,j]:=x;
    end;
   close(f);
 End;
Procedure minim(var Dm:matr);
var i,j,k:integer;
 Begin
   Dm:=c;
   for k:=1 to n do
    for i:=2 to n do
     for j:=1 to n do
       if (k<>i) and(k<>j)
         then if Dm[i,k]+Dm[k,j]<Dm[i,j]
                  then Dm[i,j]:=Dm[i,k]+Dm[k,j];
 End;
BEGIN
clrscr;
citire(c,n);
minim(Dm);
for i:=1 to n do
 begin
 for j:=1 to n do
  Write(Dm[i,j],' ');
  writeln;
 end;
readkey;

end.

loading...