Documente Academic
Documente Profesional
Documente Cultură
Raport
Matematici Speciale
Chişinău 2020
Scopul lucrării:
Note teoretice :
1. Graf ponderat se numește un graf în cadrul căruia fiecărui arc îi este asociată o
valoare. Valoarea asociată arcului are semnificația de "cost" a legăturii între cele 2
noduri sau de "distanță " între noduri.
2. Lungimea drumului minim vom numi Distanță.
3. Algoritmul Ford conţine următorii paşi :
Fiecărui vârf xj al grafului G se va ataşa un număr foarte mare H j(∞). Vârfului
iniţial i se va ataşa Ho = 0;
Se vor calcula diferenţele Hj - Hi pentru fiecare arc (xi, xj). Sunt posibile trei cazuri:
a) Hj - Hi < Lij,
b) Hj - Hi = Lij,
c) Hj - Hi > Lij.
Cazul "c" permite micşorarea distanţei dintre vârful iniţial şi xj din care cauză se va realiza
Hj = Hi + Lij.
Pasul 2 se va repeta atâta timp cât vor mai exista arce pentru care are loc inegalitatea “c”.
La terminare, etichetele Hi vor defini distanţa de la vârful iniţial până la vârful dat xi.
Acest pas presupune stabilirea secvenţei de vârfuri care va forma drumul minim. Se va
pleca de la vârful final xj spre cel iniţial. Predecesorul lui xj va fi considerat vârful xi
pentru care va avea loc Hj - Hi = Lij. Dacă vor exista câteva arce pentru care are loc
această relaţie se va alege la opţiune.
4. Etapele principale în algoritmul Bellman-Kalaba sunt :
Etapa iniţială presupune ataşarea grafului dat G a unei matrice ponderate de adiacenţă,
care se va forma în conformitate cu următoarele:
M(i,j) = Lij, dacă există arcul (xi, xj) de pondere Lij;
M(i,j) = ∞, unde ∞ este un număr foarte mare (de tip întreg maximal pentru
calculatorul dat), dacă arcul (xi, xj) este lipsă;
M(i,j) = 0, dacă i = j.
La etapa a doua se va elabora un vector V0 în felul următor:
V0(i) = Lin, dacă există arcul (xi, xn), unde xn este vârful final pentru care se caută drumul
minim, Lin este ponderea acestui arc;
V0(i) = ∞, dacă arcul (xi, xn) este lipsă;
V0(i) = 0, dacă i = j.
Algoritmul constă în calcularea iterativă a vectorului V în conformitate cu următorul
procedeu:
Vk(i) = min{Vk-1; Lij+Vk-1(j)}, unde i = 1, 2,…, n - 1, j = 1, 2,..., n; i<>j;
Vk(n) = 0.
Când se va ajunge la Vk = Vk-1 - STOP.
5. Algoritmul Ford permite determinarea drumului minim care începe cu un vârf
iniţial xi până la oricare vârf al grafului G , însă algoritmul Bellman-Kalaba permite
determinarea drumului minim dintre oricare vârf al grafului până la un vârf , numit
vârf final.
6. Se va pleca de la vârful final xj spre cel iniţial. Predecesorul lui xj va fi considerat
vârful xi pentru care va avea loc Hj - Hi = Lij. Dacă vor exista câteva arce pentru
care are loc această relaţie se va alege la opţiune.
Sarcina de bază :
1. Elaboraţi procedura introducerii unui graf ponderat;
2. Elaboraţi procedurile determinării drumului minim și maxim;
3. Realizaţi un program cu următoarele funcţii:
introducerea grafului ponderat cu posibilităţi de analiză sintactică şi semantică şi
de corectare a informaţiei;
determinarea drumului minim și maxim;
extragerea informaţiei la display şi printer (valoarea drumului minim, maxim şi
succesiunea vârfurilor care formează acest drum)
Matricea de adiacență
A
X X X X X X X X
1 2 3 4 5 6 7 8
X 1
0 0 1 1 0 0 0 0
X 2
0 0 0 0 1 1 0 0
X 3
0 1 0 0 0 1 0 0
X 4
0 0 0 0 0 1 1 0
X 5
0 0 0 0 0 1 0 1
X 6
0 0 0 0 0 0 1 1
X 7
0 0 0 0 0 0 0 1
X 8
0 0 0 0 0 0 0 0
Codul programului :
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define MAX 30000
void F();
void BK();
void Menu();
void ListAd();
void ElebList();
void DrumFord(int);
struct Lista_incidenta{
int v;
int w;
struct Lista_incidenta *next;};
struct Graph{
int h;
int p;
struct Lista_incidenta *first;
struct Lista_incidenta *last;}*G;
int N,V;
void Ford()
{ int i,f=1;
struct Lista_incidenta *c;
if(G==NULL) return;
for(i=0;i<N;i++)
{ G[i].p=-1;
G[i].h=MAX;}
printf("\n\t");
printf("Dati virful initial: ");
scanf("%d",&V);
G[--V].h=0;
while(f)
{ f=0;
for(i=0;i<N;i++)
{ c=G[i].first;
while(c!=G[i].last)
{ if(G[c->v].h>G[i].h+c->w)
{ G[c->v].h=G[i].h+c->w;
G[c->v].p=i;
f=1;}
c=c->next;}
}
}
for(i=0;i<N;i++)
{ printf("\n\r Drum min din %d in %d este",V+1,i+1);
if(G[i].h==MAX) {printf(" nu exista.");}
else
{ DrumFord(i);
printf(" : Lungimea %d.\n",G[i].h);
}
}
}
void Bel_Kal()
{ int *t,i,j,k,f=1;
struct Lista_incidenta *c;
int *P=(int *)malloc(N*sizeof(int ));
int *VK=(int *)malloc(N*sizeof(int ));
int **M=(int **)malloc(N*sizeof(int *));
int *VK_1=(int *)malloc(N*sizeof(int ));
for(i=0;i<N;i++) M[i]=(int *)malloc(N*sizeof(int));
for(i=0;i<N;i++)
for(j=0;j<N;j++) M[i][j]=(i==j)?0:MAX;
for(i=0;i<N;i++)
{ c=G[i].first;
while(c!=G[i].last)
{ M[i][c->v]=c->w;
c=c->next;
}
}
printf("\n\t");
printf("Dati virful final: ");
scanf("%d",&V);
V--;
for(i=0;i<N;i++)
{ VK_1[i]=M[i][V];
P[i]=-1;
}
while(f)
{ for(i=0;i<N;i++) VK[i]=MAX;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
if(i!=j && VK[i]>VK_1[j]+M[i][j])
{ VK[i]=VK_1[j]+M[i][j];
P[i]=j;
}
VK[V]=0;
for(i=0;i<N && VK[i]==VK_1[i];i++);
f=(i==N)?0:1;
t=VK_1; VK_1=VK; VK=t;
}
for(i=0;i<N;i++)
{ printf("\n Drumul min din %d in %d este",i+1,V+1);
if(VK_1[i]==MAX) { printf(" nu exista.");}
else
{ for(k=i,j=0;j<N && P[k]!=-1 && k!=V;j++)
{ if(!j) printf(": %d",k+1);
else printf("->%d",k+1);
k=P[k];
}
if(k==V || i<N-1) printf("->%d",V+1);
else printf(": %d",V+1);
printf(" : Lungimea: %d.\r",VK_1[i]);
}
}
for(i=0;i<N;i++) free(M[i]);
free(P); free(M); free(VK); free(VK_1);
}
void ListAd()
{ int i,v,w;
struct Lista_incidenta *c;
if(G) ElebList();
printf("\n\t");
printf("Dati nr de virfuri a grafului : ");
scanf("%d",&N);
G=(struct Graph *)malloc(N*sizeof(struct Graph));
printf("\n\t");
printf("Introduceti Lista_incidentaa de adiacenta: \n\n\r");
for(i=0;i<N;i++)
{ printf("%d|",i+1);
G[i].first=(struct Lista_incidenta*)malloc(sizeof(struct Lista_incidenta));
G[i].last=G[i].first;
G[i].last->next=NULL;
G[i].last->v=-1;
scanf("%d",&v);;
if(N<v || v<0)
{ system("cls");
printf("\n\n\n\n\n\t\t\t");
printf("Eroare!");
}
while(v)
{ G[i].last->v=v-1;
G[i].last->next=(struct Lista_incidenta*)malloc(sizeof(struct Lista_incidenta));
G[i].last=G[i].last->next;
G[i].last->next=NULL;
G[i].last->v=-1;
scanf("%d",&v);
if(N<v || v<0)
{ system("cls");
printf("\n\n\n\n\n\t\t\t");
printf("Eroare!");
}
}
}
system("cls");
printf("\n\t");
printf("Introduceti ponderea pentru fiecare arc:\n\n\r");
for(i=0;i<N;i++)
{ G[i].last=G[i].first;
while(G[i].last->v+1)
{ printf(" u%d%d| ",i+1,G[i].last->v+1);
scanf("%d",&w);
G[i].last->w=w;
G[i].last=G[i].last->next;
}
}
}
void ElebList()
{ struct Lista_incidenta *c,*t;
while(N--)
{ c=G[N].first;
while(c!=G[N].last)
{ t=c->next;
free(c);
c=t;}
}
free(G);}
void DrumFord(int v)
{ int k;
if(v!=V) {k=v; DrumFord(G[v].p);}
if(k!=v) printf(": %d",v+1);
else {printf("->%d",v+1); k++;}
}
int main()
{
int optiune;
do
{
system("CLS");
printf(" \t\t\t \t\t- MENU -\n");
puts(" \t\t***********************************************************");
puts(" \t\t*\t 1.Introducerea grafului *");
puts(" \t\t*\t 2.Algoritmul Ford *");
puts(" \t\t*\t 3.Algoritmul Bellman-Kalaba *");
puts(" \t\t*\t 0.Iesire *");
puts(" \t\t***********************************************************");
printf("\n Alegeti optiunea: ");
scanf("%d",&optiune);
switch (optiune){
case 1:
{
ListAd();
break;
}
case 2:
{
Ford();
break;
}
case 3:
{
Bel_Kal();
break;
}
}
}
while(optiune!=0);
}
Rezultatul :
Concluzia :