Documente Academic
Documente Profesional
Documente Cultură
perechi ordonate de elemente distincte din V, ale crei elemente se numesc arce.
Exemplu de graf orientat:
G=(V, U) unde:
V={ 1,2,3,4,5,6}
U={{1,5}, {2,1},{3,6},{4,1},{4,3},{5,2},{6,4},{6,5}}
#include<iostream.h>
int s[20],a[20][20],n,L,i,j;
void afisare_drum()
{int i; cout<<endl;
for(i=1;i<=n;i++)
cout<<s[i]<<" ";}
void generare_drum()
{int i,j,k,p,q;
if(a[1][2]==1)
{s[1]=1;
s[2]=2;}
else
{s[1]=2;
s[2]=1;}
L=2;
for(k=3;k<=n;k++)
{if(a[k][s[1]]==1)
p=1;
else
{i=1;
q=0;
while(i<L&&!q)
if(a[s[i]][k]==1&&a[k][s[i+1]]==1)
q=1;
else i++;
p=i+1;}
for(j=L;j>=p;j--)
s[j+1]=s[j];
s[p]=k;
L++;}
cout<<endl;}
int main()
{cout<<"n=";cin>>n;
for(i=1;i<=n-1;i++)
for(j=i+1;j<=n;j++)
{cout<<"exista arcul ("<<i<<","<<j<<")?[1/0]";
do
{cin>>a[i][j];}
while(!(a[i][j]==0 || a[i][j]==1));
a[j][i]=1-a[i][j];}
generare_drum();
afisare_drum();
return 0;}
6. Lan
Fie G=(V, U) un graf orientat. Se numeste lan, n graful G, o succesiune de arce cu proprietatea c ori-care
dou arce consecutive au o extremitate comun (nu are importan orientarea arcelor).
Se ntlnesc noiunile:
extremitile lanului fiind dat lanul Lse numesc extremiti ale sale extremitatea arcului ui1 care nu
este comun cu arcul ui2 si extremitatea arcului uik care nu este comun cu arcul uik-1
7. Drum
Numim drum o succesiune de noduri care au proprietatea c oricare ar fi dou noduri succesive acestea sunt
legate printr-un arc. Un drum poate fi:
Elementar - un drum care conine doar noduri distincte. (fig 1)
Neelementar - un drum care nu conine doar noduri distincte. (fig 2)
Simplu - un drum care conine doar muchii distincte.
Compus - un drum care nu conine doar muchii distincte.
Fig. 1
Fig.2
8. Circuit
Numim circuit un drum n care toate arcele sunt distincte dou cte dou i exist un arc de la ultimul nod la
primul (numrul minin de noduri este 3). Un circuit poate fi:
Elementar - un circuit care conine doar noduri distincte (cu excepia primului i a ultimului, care
coincid). (fig. 1)
Neelementar - un circuit care nu conine doar noduri distincte (cu excepia primului i a ultimului, care
coincid). (fig. 2)
Fig.1
Fig. 2
Noiunea de lan/ciclu este valabil i n cazul grafurilor orientate (nu are importan sensul arcelor).
La drumuri/circuite toate arcele trebuie s aib aceeai orientare.
9.Grafurile n viaa de zi cu zi
Un exemplu de graf orientat este: reeaua de strzi a unui ora. Strzile sunt arcele n graf, iar interseciile
reprezint vrfurile grafului. ntruct mergnd pe jos ne putem deplasa pe orice strad n ambele sensuri, vom
spune c din punctul de vedere al pietonilor, graful unui ora este neorientat.
Cu totul altfel stau lucrurile n ceea ce privete conductorii auto, pentru c n orice ora exist strzi cu sens
unic. Pentru un ofer strzile trebuie s primeasc n graf o anumit orientare. Desigur c acele strzi pe care se
poate circula n ambele sensuri vor primi orientare dubl.
Alte exemple ar fi: circulaia sngelui n organism (sngele circul prin artere de la inim n corp, i prin vene
din corp spre inim), cunotinele (exist persoane pe care le cunoatem, dar ele nu ne cunosc pe noi, sau persoane
care ne cunosc, dar noi nu le cunoatem, sau persoane care ne cunosc i le cunoatem).
II.Reprezentare
Pentru a reprezenta un graf orientat, ntr-un program, exist mai multe modaliti folosind diverse structuri de
date; dintre acestea n continuare vom prezenta:
reprezentarea prin matricea de adiacen;
reprezentarea prin matricea vrfuri-arce;
reprezentarea prin matricea drumurilor;
reprezentarea prin listele de adiacen;
reprezentarea prin sirul arcelor.
1Matricea de adiacen
for (j=1;j<=n;j++)
s=s+a[i][j];
return s;}
4.Numrul elementelor egale cu 1 de pe coloana i este egal cu gradul interior al vrfului i.
int gr int(int i) // determinarea gradului exterior al unui nod i
{int j, s;
s=0;
for (j=1;j<=n;j++)
s=s+a[j][i];
return s;}
5.Dac vrful i este un vrf izolat, pe linia i si coloana i nu sunt elemente egale cu 1.
int vf_izolat(int i)
{return (gr_ext(i)==0) && (gr_int(i)==0);
}
2.Matricea vrfuri-arce ( matricea de inciden)
3 Matricea drumurilor
4.Lista de adiacen
Fie G=(V, U) un graf orientat, cu n vrfuri (V={ 1,2, ..., n}) si m arce.
Reprezentarea grafului G, prin liste de adiacen, const n:
- precizarea numrului de vrfuri n;
- pentru fiecare vrf i, se precizeaz lista L; a succesorilor si, adic lista nodurilor care
fac parte din
mulimea +(i).
Reprezentarea in calculator a unui graf se poate face utilizand listele de adiacenta a varfurilor, adic pentru
fiecare varf se alcatuiete lista vrfurilor adiacente cu el.
Fie graful din figura urmatoare:
Lista vecinilor varfului 5: 3, 4 (noduri adiacente) Pentru intreg graful vom avea mai multe liste :
Varful 1:
Varful 2 :
Varful 3 :
Varful 4 :
Varful 5 :
Varful 6
Ordinea varfurilor in cadrul unei liste nu este important. Pentru a genera o astfel de lista vom defini tipul nod :
struct nod {int nd;
nod *next;};
Toate listele se vor memora utiliznd un vector de liste :
nod *L[20];
Datele de intrare : numarul de varfuri si arcele se vor citi din fisier .O solutie de implementare este urmatoarea :
#include<iostream.h>
#include<fstream.h>
struct nod
{int nd;
nod *next;};
nod *L[20];
void afisare(int nr_nod) //afiseaza lista vecinilor varfuluii nr_nod
{nod *p=L[nr_nod];
if(p!=0)
{cout<<"lista vecinilor lui "<<nr_nod<<endl;
nod *c=p;
while(c)
{cout<<c->nd<<" ";
c=c->next;}
cout<<endl;}
}
int main()
{fstream f;int i,j,n;
nod *p,*q;
f>>n;
while(f>>i>>j)
{p=new nod; //se adauga j in lista vecinilor lui i
p->nd=j;
p->next=L[i];
L[i]=p;
}
f.close();
cout<<endl<<"listele de adiacente ";
for(i=1;i<=n;i++)
afisare(i);
}
Observatie : n exemplul anterior adugarea unui nou element n lista se face nainte celorlalte din lista
corespunzatoare.
Aceste dou moduri de reprezentare (prin matrice de adiacen i prin liste de vecini) se folosesc dupa natura
problemei. Adic, daca n problem se dorete un acces frecvent la arce, atunci se va folosi matricea de adiacen;
dac numrul de arce care se reprezint este mult mai mic dect nxn, este de preferat s se folosesc listele de
adiacen, pentru a se face economie de memorie.
Construirea matricei de adiacen, cnd se cunoaste L (listele vecinilor fiecrui nod).
..................
for (i=1;i<=n;i++)
{for (j=1;j<=nr_vec[i];j++)
a[i][L[i][j]]=1;}
..................
5 irul arcelor
Fie G=(V, U) un graf orientat, cu n vrfuri (V={ 1,2, ..., n}) si m arce.
Reprezentarea grafului G const n precizarea numrului n de noduri i numrului m de
arce precum i n
precizarea extremitilor pentru fiecare arc n parte.:
Acest mod de reprezentare se implementeaz astfel:
1. Se d numrul n de noduri i numrul m de arce, iar extremitile fiecrui arc sunt trecute
n vectorii el i
e2, astfel:
- extremitile primului arc sunt el[1] i e2 [1];
- extremitile celui de-al doilea arc sunt e1[2] si e2[2];
- deci, U={( el[1],e2[1]) , (el[2],e2[2]) ,..., ( el [m],e2[m])}
Secvena C++corespunztoare este:
................
k=0;
for (i=1;i<=n;i++)
for (j==1;j<=n;j++)
if (a[i][j] ==1)
{ k=k+1;
e1[k]=i;
e2[k]=j;}
m=k;
.................
IV. Parcurgerea
Rezolvarea multor probleme de grafuri, presupune parcurgerea lor de la un anumit nod. Pentru explorarea
grafurilor, exist dou tipuri de algoritmi: de explorarea n lime i de explorare n adncime. Parcurgerea
grafurilor orientate este similar cu a grafurilor neorientate, se ine cont ns de orientare.
4.1 Explorarea grafurilor n lime
La explorarea n lime, dup vizitarea vrfului iniial, se exploreaz toate vrfurile adiacente lui, se trece apoi la
primul vrf adiacent i se exploreaz toate vrfurile adiacente acestuia i neparcurse nc, s.a.m.d.
Fiecare vrf se parcurge cel mult odat.
De exemplul pentru graful din figura de mai jos, se va proceda n felul urmtor: se pornete din nodul 1, (se
poate ncepe de la oricare alt nod)
se obine 1,2,4
dupa care din 2 se exploreaz nodul adiacent acestuia 3. Nodul 1 nu se mai viziteaz odata
se obine 1,2,4,3
n continuare ar trebui parcuri vecinii lui 4 (1,2,4,3 ) dar acesta nu mai are vecini nevizitai i se trece la vecinii
lui 3 : 1,2,4,3 respectiv nodul 5 :
10
se obine 1, 2, 4, 3, 5
Vrful 6 rmne neparcurs .
Dac se parcurge graful ncepnd de la vrful 2, soluia este : 2,3,4,5, n timp ce parcurgerea ncepnd cu 4 va
reine doar vrful 4
Algoritmul
Se va folosi o coad n care se nscriu nodurile n form n care sunt parcurse: nodul iniial vrf (de la care se
pornete), apoi varfurilr a,b,..., adiacente lui vrf, apoi cele adiacente lui a, cele adiacente lui b,... ,.a.m.d.
Coad este folosit astfel:
- se ncrca primul vrf n coad;
- se afl toate vrfurile adiacente cu primul nod i se ntroduc dup primul vrf
- se ia urmtorul nod i i se afl nodurile adiacente
- procesul se repet pn cnd se ajunge la sfritul cozii
-Graful se va memora utiliznd matricea de adiacen a[10][10]
-pentru memorarea succesiunii vrfurilor parcurse se va folosi un vector c[20] care va funciona c o coad
-pentru a nu parcurge un vrf de dou ori se va folosi un vector boolean viz[20] care va reine :
- viz[k]=0 dac vrful k nu a fost vizitat nc
- viz[k]=1 dac vrful k a fost vizitat
-dou variabile : prim i ultim vor reine dou poziii din vectorul c i anume :
- prim este indicele componenei pentru care se parcurg vecinii (indexul
componentelor marcate cu rou n irurile parcurse anterior ). Prin urmare Varf=c[prim], este elementul pentru
care se determin vecinii (vrfurile adiacente)
-ultim este poziia n vector pe care se va face o noua inserare n vectorul c
(evident, de fiecare data cnd se realizeaz o noua inserare se mrete vectorul)
-vecinii unui vrf se caut pe linia acestui vrf : dac a[vrf][k]=1 nseamn c vrf i k sunt adiacente.
Pentru ca vrful k s fie adugat n coad trebuie c vrful s nu fi fost vizitat : viz[k]=0
#include<fstream.h>
#include<iostream.h>
int a[10][10],c[20],viz[10];
int n,m,prim,ultim,varf;
ifstream (date.in);
void bf_iterativ() //parcurgerea n lime
{int k;
while(prim<=ultim)
{varf=c[prim];
for(k=1;k<=n;k++)
if(a[varf][k]==1&&viz[k]==0) //l adaug pe k n coad dac este vecin pt. vrf i nu a fost vizitat
{ultim++;
c[ultim]=k;
viz[k]=1;}
prim++;
}
}
void main()
{clrscr();
int x,y;
f>>n>>m;
for(int i=1;i<=m;i++)
{f>>x>>y;
a[x][y]=1;
}
cout<<"matricea de adiac "<<endl; // afiare matrice de adiacenta
for( i=1;i<=n;i++)
{for(int j=1;j<=n;j++)
11
cout<<a[i][j]<<" ";
cout<<endl;
}
int nd;
prim=ultim=1;
cout<<"varful de inceput=";
cin>>nd; // varful de la care se porneste parcurgerea
viz[nd]=1;
c[prim]=nd;
bf_iterativ();
for(i=1;i<=ultim;i++) //afiarea cozii
cout<<c[i]<<" ";
return 0; }
Varianta recursiva de parcurgere se obine modificnd funcia de parcurgere iterativ adaugnd condiia necesar
autoapelului:
void bf_recursiv() //parcurgerea n lime
{int k;
if(prim<=ultim)
{varf=c[prim];
for(k=1;k<=n;k++)
if(a[varf][k]==1&&viz[k]==0) //l adaug pe k n coad dac este vecin pt. vrf i nu a fost vizitat
{ultim++;
c[ultim]=k;
viz[k]=1;}
prim++;
bf_recursiv();
}
}
Parcurgerea n laime a grafurilor memorate prin liste este similar cu diferena c vecinii unui nod adaugat n
coad se caut n lista corespunzatoare lui :
#include<iostream.h>
#include<fstream.h>
Ifstream (date.in);
struct nod
{int nd;
nod *next;};
nod *L[20];
int viz[100]; //marchez cu 1 nodurile vizitate
int m,n;
int prim,ultim,C[100];
void bfi_lis()
{int varf,nr;
nod *p;
while(prim<=ultim)
{varf=C[prim];
p=L[varf]; // se parcurge lista elementelor din varful cozii
while(p)
{nr=p->nd;
if(viz[nr]==0) //numai dac nu a fost vizitat
{ultim++; //mresc coada
C[ultim]=nr; //l adaug n coad
viz[nr]=1;}; //l marchez ca fiind vizitat
p=p->next;}
prim++; //avansez la urmtorul vrf din coad }
}
void afisare(int nr_nod)
{nod *p=L[nr_nod];
if(p==0)
cout<<nr_nod<<" este izolat "<<endl;
else
{cout<<"lista vecinilor lui "<<nr_nod<<endl;
nod *c=p;
while(c)
12
{cout<<c->nd<<" ";
c=c->next;}
cout<<endl;}
}
void main()
{fstream f;
int i,j;
nod *p,*q;
f>>n>>m;
while(f>>i>>j)
{p=new nod;
p->nd=j;
p->next=L[i];
L[i]=p;
}
f.close();
cout<<endl<<"listele de adiacen ";
for(i=1;i<=n;i++)
afisare(i);
int ndr;
cout<<endl<<"nodul de nceput ";
cin>>ndr;
viz[ndr]=1;
prim=ultim=1;
C[prim]=ndr;
cout<<endl<<"parcurgere n laime "<<endl;
bfi_lis();
for(i=1;i<=ultim;i++)
cout<<C[i]<<" ";
return 0;}
Funcia recursiv :
void bfr_lis()
{int varf,nr;
nod *p;
if(prim<=ultim)
{varf=C[prim];
p=L[varf];// se parcurge lista elementelor din vrful cozii
while(p)
{nr=p->nd;
if(viz[nr]==0)//numai daca nu a fost vizitat
{ultim++;//mresc coada
C[ultim]=nr;//l adaug n coad
viz[nr]=1;};//l marchez ca fiind vizitat
p=p->next;}
prim++; //avansez la urmtorul nod din coad
bfr_lis();
}
}
13
dupa care din 2 se exploreaz vrful adiacent cu acesta i care nu a fost vizitat : 3.
se obtine 1,2,3
n continuare ar trebui s se parcurg vecinul lui 3 nevizitat : 4
se obine 1, 2, 3, 4
Pentru varful 4 ar trebui s se parcurg primul su vecin neparcurs (varful 1 dar acesta a fost deja parcurs. Nu
mai avem ce vizita i se trece la nivelul anterior din stiv, la vrful 3 :
1, 2, 3, 4 Se parcurge vecinul sau nevizitat, varful 5 .
Se obine : 1, 2, 3, 4 , 5.
Vrful 3 nu mai are vecini nevizitati i se trece pe nivelul anterior din stiv, vrful 2 : 1, 2, 3, 4 , 5. Nici acesta
nu mai are vecini nevizitati i se trece pe nivelul anterior la vrful 1 : 1, 2, 3, 4 , 5. Cum nici acesta nu mai are
vecini nevizitati se ncheie algoritmul. Vrful 6 rmne nevizitat.
Algoritmul
-Graful se va memora utiliznd matricea de adiacen a[10][10]
-pentru a nu parcurge un vrf de dou ori se va folosi un vector boolean viz care va reine :
- viz[k]=0 dac vrful k nu a fost vizitat nc
- viz[k]=1 dac vrful k a fost vizitat
14
-c i la parcurgerea n lime vecinii unui vrf se caut pe linia acestui vrf : dac a[nod][k]=1 nseamn c
vrfurile nod i k sunt adiacente. Pentru c vrful k s fie fie parcurs trebuie c vrful s nu fi fost vizitat :
viz[k]=0
#include<fstream.h>
#include<iostream.h>
int a[20][20],n,m,viz[100],gasit;
void dfmr(int nod)
{
cout<<nod<<" ";
viz[nod]=1;
for(int k=1;k<=n;k++)
if(a[nod][k]==1&&viz[k]==0)
dfmr(k);
}
void main()
{int x,y,j;
ifstream f(date.in);
f>>n>>m;
for(int i=1;i<=m;i++)
{f>>x>>y;
a[x][y]=1;}
cout<<endl<<"matricea de adiacente"<<endl;
for(i=1;i<=n;i++)
{for(j=1;j<=n;j++)
cout<<a[i][j]<<" ";
cout<<endl;}
cout<<endl<<"parcurgere in adancime incepand de la varful 1"<<endl;
dfmr(1);
return 0;}
V.Conexitate
Definiie. Fie G=(V, U) un graf orientat. Graful G se numete conex dac pentru oricare dou vrfuri x s i y, x
diferit y, exist un lant de extremiti x i y.
Fie G=(V, U) un graf orientat. Se numete component conex un graf orientat G1=(V1 ,U1) care verific
urmtoarele condiii:
este subgraf al grafului G;
este conex;
nu exist nici un lan n G care s lege un nod din V, cu un nod din V-V1.
Fie G=(V, U) un graf orientat. Graful G se numete tare conex, dac pentru oricare dou vrfuri x si y exist un
drum n G de la x la y si un drum de la y la x.
15
16
}
void face_sirul(sir x, int nx, sir y, int& ny)
{int i;
ny=0;
for (i=1;i<=nx;i++)
{ny++;
y[ny]=x[i]; }
}
int main()
{ cout<<"n="; cin>>n;
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if (i==j)
c[i][j]=0;
else c[i][j]=p_inf;
cout<<"m="; cin>>m;
for (i=1;i<=m;i++)
{cout<<"x y val " ; cin>>x>>y>>val;
c[x][y]=val;}
for (i=1;i<=n;i++)
{for (j=1;j<=n;j++)
cout<<c[i][j]<<" ";
cout<<endl;}
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if ((i!=j) && (c[i][j]<p_inf))
{ nd[i][j]=1;
d[i][j][1]=i;}
else nd[i][j]=0;
for (k=1;k<=n;k++)
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if (c[i][j]==c[i][k]+c[k][j])
reuneste(d[i][j],nd[i][j],d[k][j],nd[k][j],d[i][j],nd[i][j]);
else if (c[i][j]>c[i][k]+c[k][j])
{ c[i][j]=c[i][k]+c[k][j];
face_sirul(d[k][j],nd[k][j],d[i][j],nd[i][j]);}
afis();
return 0;}
4
17
Intersecia celor doi vectori reprezint componenta tare conexa creia i aparine vrful 4.
Iat o modalitate de rezolvare :
#include<fstream.h>
#include<iostream.h>
int a[20][20],n,m,suc[100],prec[100],x;
void dfsuc(int nod)
{suc[nod]=x;
for(int k=1;k<=n;k++)
if(a[nod][k]==1&&suc[k]==0)
dfsuc(k);
}
void dfprec(int nod)
{ prec[nod]=x;
for(int k=1;k<=n;k++)
if(a[k][nod]==1&&prec[k]==0)
dfprec(k);
}
int main()
{int y,j;
fstream f(date.in);
f>>n>>m;
for(int i=1;i<=m;i++)
{f>>x>>y;
a[x][y]=1;}
cout<<endl<<"matricea de adiacente"<<endl;
for(i=1;i<=n;i++)
{for(j=1;j<=n;j++)
cout<<a[i][j]<<" ";
cout<<endl;}
cout<<"x=";cin>>x;
dfsuc(x);
cout<<endl<<"succesorii lui "<<x<<endl;
for(i=1;i<=n;i++)
if(suc[i]!=0)
cout<<i<<" ";
dfprec(x);
cout<<endl<<"Predecesorii lui "<<x<<endl;
for(i=1;i<=n;i++)
if(prec[i]!=0)
cout<<i<<" ";
cout<<endl<<"componenta tare conexa in care se gaseste "<<x<<" este "<<endl;
for(i=1;i<=n;i++)
if(prec[i]==suc[i]&&suc[i]!=0)
cout<<i<<" "
return 0;}
0
7
3
2
0
2
0
18
Ne propunem s determinm costul minim de la un vrf la toate celelalte vrfuri. Fie acesta vrful 1.
Vom utiliza 3 vectori : Vectorul d care va reine lungimea drumurilor de la 1 la celelalte vrfuri. (d[i]=lungime
drum de la 1 la i). Iniial d reine :
0
Vectorul s, numit vector caracteristic va reine 1 pentru nodurile selectate ca participante la drumul minim, altfel
s reine 0. Iniial va reine 1 doar pentru vrful de pornire , n cazul nostru vrful
1
Vectorul t , vector de tip tat care va indica drumurile gsite ntre vrful 1 i celelalte vrfuri astfel nct pentru
fiecare vrf se va retine precedentul (tatl). Pentru vrful de pornire, 1 n cazul nostru, se reine 0. Iniial t va
reine :
1
Algoritmul :
Se pornete de la vrful 1(r=1, unde r are valoare de rdcin) . Se marcheaz n s cu 1 : s[r]=1
Matricea costurilor:
0
1
9
0
7
3
2
0
2
0
Vectorul s :
1
Vectorul t :
0
19
min=1, vf=2
se marcheaz n s :
Vectorul s :
1
n continuare se pune problema dac pentru nodurile neadugate nc nu s-ar putea realiza mbuntiri ale
lungimii drumurilor prin 2:
Adic pentru un vrf x daca d[x]>d[vf]+a[vf][x] atunci se realizeaz modificarea efectiv n d i se adaug vf ca
fiind predecessor (tata) pentru x:
if(d[x]>d[vf]+a[vf][x])
{ d[x]=d[vf]+a[vf][x];
t[x]=vf; }
Vectorul s :
1
Vectorul t :
0
Mai sunt de adugat vrfurile 3,4, 5. Acestea se pot aga de vrfurile adugate (selectate) fie 1 fie 2.
Se procedeaz la fel : se determin cel mai apropiat vrf : min =3 si vf=5
Vectorul d :
0
Se selecteaz n s : s[vf]=1:Vectorul s :
20
Dar nu se mai pot obine mbuntiri ale drumurilor de la 1 la vrfurile rmase (3 sau 4) care s treac prin 5
prin urmare vectorul t rmne acelai :
Vectorul t :
0
Vectorii devin:
Vectorul d :
0
Vectorul s :
21
Vectorul t :
0
Vectorul s :
1
Vectorul t :
Soluie de implementare :
#include<fstream.h>
#include<iostream.h>
const pinf=1000;
ifstream f(date.in);
int a[20][20],n,m;
int r;//varful de inceput
int s[100],int d[100],t[100];
void citire_cost()
{ int i,j,x,y,c;
f>>n>>m;
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]=c;}
}
void afisare_mat()
{cout<<endl<<"matricea costurilor"<<endl;
22
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 afiseaza_vector(int v[100])
{for(int i=1;i<=n;i++)
cout<<v[i]<<" ";
cout<<endl;}
void cauta_min(int &vf)//caut varful cel mai apropiat de r care nu a fost selectat inca
{int min=pinf;
for(int i=1;i<=n;i++)
if(s[i]==0)
if(d[i]<min)
{min=d[i];
vf=i;}
}
void imbunatatire_drum(int vf)//incerc sa imbunatatesc drumurile de la r la varfurile neselectate inca prin el
{for(int i=1;i<=n;i++)
if(s[i]==0)
if(d[i]>d[vf]+a[vf][i])
{d[i]=d[vf]+a[vf][i];
t[i]=vf;//l adaug pe vrf ca posibil printe pentru i
}
}
void drum(int i)
{if(t[i])
drum(t[i]);
cout<<i<<" ";
}
int main()
{int vf,min;
citire_cost();
afisare_mat();
cout<<"nodul de inceput?";
cin>>r;
for(int i=1;i<=n;i++)
if(i!=r)
{d[i]=a[r][i];
if(a[r][i]!=pinf)
t[i]=r;
}
for(i=1;i<=n-1;i++)
{cauta_min(vf);//caut varful cel mai apropiat de r care nu a fost selectat inca
s[vf]=1; //il selectez ca fiind vizitat
imbunatatire_drum(vf);//incerc sa imbunatatesc drumurile de la r la varfurile neselectate inca prin el
}
cout<<endl;
cout<<"vectorul drum: "<<endl;
afiseaza_vector(d);
cout<<"vectorul critic: "<<endl;
afiseaza_vector(s);
cout<<"vectorul de tati: "<<endl;
afiseaza_vector(t);
for(i=1;i<=n;i++)
if(i!=r)
if(t[i]!=0)//daca vectorul a fost adaugat la arbore
{cout<<"drumul de la "<<r<<" la "<<i<<" este :"<<endl;
drum(i);
cout<<endl<<"si are lungimea "<<d[i]<<endl<<endl;}
else
cout<<"nu exista drum de la "<<r<<" la "<<i<<endl;
return 0;
23
24
}
int main()
{ int vf,min;
citire_cost();
afisare_mat();
cout<<"nodul de inceput?";
cin>>r;
s[r]=1;
cout<<"k=";
cin>>k;
for(int i=1;i<=n;i++)
if(i!=r)
{d[i]=a[r][i];
if(a[r][i]!=pinf)
t[i]=r; }
for(i=1;i<=n-1;i++)
{cauta_min(vf); //caut varful cel mai apropiat de r care nu a fost selectat inca
s[vf]=1; //il selectez ca fiind vizitat
imbunatatire_drum(vf);//incerc sa imbunatatesc drumurile de la r la varfurile neselectate inca prin el
}
cout<<endl;
cout<<"vectorul drum: "<<endl;
afiseaza_vector(d);
cout<<"vectorul critic: "<<endl;
afiseaza_vector(s);
cout<<"vectorul de tati: "<<endl;
afiseaza_vector(t);
int y;
cout<<"vf final=";
cin>>y;
cout<<endl;
if(d[y]==pinf)
cout<<"nu exxista solutie";
else
cout<<"drumul minim cu maxim k vrfuri impare are valoarea "<<d[y];
cout<<endl;
drum(y);
return 0;}
25