Elev: Tarbuc Eugen-Cosmin CNAIC, 12 B Profesor coordonator: Magdalena Grigore
CUPRINS 1
Argument ……………………………………………………………….3 GRAFURI NEORIENTATE
1. Definitie……………… Definitie……………………………… …………………………… …………………………. ……………..4 .4 2. Gradul Gradul unui nod……………… nod……………………… ……………… ……………… ……………… …………..4 …..4 3. Graf Partial………………… Partial……………………………… …………………………… ………………………..5 ………..5 4. Subgraf… Subgraf………… ……………… ……………… ……………… ……………… ……………… ……………… …………5 …5 5. Lant………… Lant………………… ……………… ……………… ……………… ……………… ……………… ……………. …….66 6. Ciclu……… Ciclu……………… ……………… ……………… ……………… ……………… ……………… ……………… ………66 7. Graf nul…………………………… nul………………………………………… …………………………… ………………...6 ...6 8. Graf complet…………………… complet…………………………………… …………………………… ……………..…..7 ..…..7 9. Graf convex………………………… convex…………………………………..… ………..………………… …………………7 …7 10.Parcurgerea in adancime……….……………...………………….8 11.Parcurgerea in latime…………………………..…………………8 12.Teoreme……………………………….…………………………..9 PROBLEME
MATRICE ADIACENTA………………………………………………………..11 GRAF PARTIAL………………………………………………………………….13
GRADELE NODURILOR…………………………...………………..15 NODURILE IZOLATE………… IZOLATE………………………… …………………………… ……………………..16 ………..16 CICLUE ELEMENTAR ……………………………………………....18 GRAF COMPLET……………………………………………………..20 GRAF CONVEX………………………………………………………22 PARCURGEREA IN LATIME………………………………………23 PARCURGEREA IN ADANCIME…………………………………...25 2
BIBLIOGRAFIE…………………………………………………….26
3
Argument
Încă de la apariţia limbajelor de programare s-a încercat ca acestea să descrie cat mai bine realitatea. Am ales graful ca temă pentru realizarea proiectului deoarece consider că grafurile au o importanţă deosebită fiind utilizaţi în domenii precum: cibernetică, matematică, cercetări operaţionale în vederea optimizării diferitelor activităţi economice, chimie (pentru descrierea structurii cristalelor), reţelele de transport de toate tipurile (pentru optimizarea traseelor), circuite electrice (pentru simularea funcţionări corecte), inteligenţa artificiala şi nu în ultimul rând în domeniul analizei aplicaţiilor software.
GRAFURI NEORINTATE
4
U
n graf neorientat este o pereche ordonată de multimi (V, M), unde: V={v1, v2, v3, …, vn} este o multime finită şi nevidă de elemente, numite noduri sau vârfuri, iar M este o multime finită de perechi neordonate, distincte, de elemente din V, de forma (vi, vj) unde i≠j şi vi, vj ∈V.
Figura 1b Gradul unui nod X reprezintă numărul de muchii incidente cu nodul X şi îl
notăm
cu d(x). Un nod X al unui graf neorientat G=(V,M) se numeşte nod izolat dacă are gradul zero. Un nod X al unui graf neorientat G=(V,M) se numeşte nod terminal dacă are gradul unu.
Exemple
Nod terminal este nodul 3 din graful neorientat iar d(3)=1. Pentru graful din Figura 1.b. gradele nodurilor sunt: d(1)=2, d(2)=2, d(3)=1, d(4)=2, d(5)=3
Un graf neorientat Gp=(V,Mp) este graf partial al unui graf G=(V,M) dacă Mp⊂M. Graful partial Gp=(V,Mp) se obtine prin eliminarea uneia sau mai multor muchii din graful G=(V,M). Considerăm graful G=(V,M) din figura a. Dacă din acest graf eliminăm muchiile (1,4) şi (3,4), obtinem graful partial Gp=(V,Mp) din figura b 5
Fig a
Fig b
SUBGRAF Un graf neorientat Gs=(Vs,Ms) este subgraf al unui graf G=(V,M) dacă Ms⊂M şi Vs⊂V. Subgraful Gs=(Vs,Ms) se obŃine prin eliminarea uneia sau mai multor noduri din graful G=(V,M) şi a tuturor muchiilor incidente cu acestea. Considerăm graful G=(V,M) din figura 3 a. Dacă din acest graf eliminăm vârful 3 şi toate muchiile incidente cu acest vârf, obtinem subgraful Gs=(Vs,Ms) al grafului G=(V,M), din figura b.
Fig a
Fig b
LANT
Se numeşte lant , o secventă de noduri ale unui graf neorientat G=(V,M), cu proprietatea că oricare două noduri consecutive sunt adiacente.
Lungimea
unui lant este dată de numărul de muchii din care 6
este format.
Se numeşte lant elementar un lant care contine numai noduri distincte.
Se numeşte lant simplu un lant care contine numai muchii distincte.
Se numeşte lant compus un lant care nu este format numai din muchii distincte.
CICLU
Se numeşte ciclu, un lant în care primul nod coincide cu ultimul şi muchiile sunt distincte două câte două.
Se numeşte ciclu elementar un ciclu care este format doar din noduri distincte, exceptie făcând primul şi ultimul nod.
GRAF NUL
Graful G=(V,M) se numeşte graf nul dacă multimea M este vidă, adică graful nu are muchii. Pentru graful nul din figura de mai jos avem:
V={1,2,3} M= ∅
GRAF COMPLET
Prin graf complet se întelege un graf neorientat în care oricare două noduri sunt adiacente.
Pentru graful complet din figura avem:
V={1,2,3,4} M={(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)} GRAF CONVEX
7
Graful G=(V,M) se numeşte graf conex dacă pentru oricare două noduri vi, vj ∈V, există un lant de la vi la vj.
Pentru graful conex din figura avem:
V={1,2,3,4,5} M={(1,3),(1,5),(2,3),(2,4),(2,5)}
Se numeşte componentă conexă a grafului G=(V,M), un subgraf conex al lui G, C=(V1,M1) cu proprietatea că nu există nici un lant în G care să lege un nod din V1 cu un nod din V-V1.
PARCURGEREA IN ADANCIME
Parcurgerea în adâncime se realizează prin vizitarea nodurilor grafului G=(V,M), în următoarea ordine:
- se vizitează nodul i
- se vizitează primul nod adiacent cu el, încă nevizitat, după care următorul nod adiacent cu el şi tot aşa până când nu mai are noduri adiacente cu el nevizitate
- se revine la nodul I şi se reiau paşii
- se încheie parcurgerea după ce se parcurg toate nodurile grafului
De exemplu, pentru graful din figura, parcurgerea în adâncime este:
- din nodul 1 -> 2, 3, 5, 4
- din nodul 2 -> 1, 3, 4, 5
- din nodul 3 -> 1, 2, 5, 4
OBS
8
Parcurgerea în adâncime depinde de ordinea de selectie a nodurilor adiacente.
PARCURGEREA IN LATIME
Parcurgerea în lătime se realizează prin vizitarea nodurilor grafului G=(V,M), în următoarea ordine:
- se vizitează nodul i
- se vizitează toate nodurile adiacente cu nodul i,respectiv i1, i2, i3, …ik
- se vizitează toate nodurile adiacente cu nodul i1, după care toate nodurile adiacente cu i2…până la ik
- se încheie parcurgerea după ce se parcurg toate nodurile grafului
De exemplu, pentru graful din figura 12.a, parcurgerea în lătime este:
- din nodul 1 -> 2, 3, 4, 5
- din nodul 2 -> 1, 3, 5, 4
- din nodul 3 -> 1, 2, 4, 5
Parcurgerea în lătime depinde de ordinea de parcurgere a nodurilor adiacente.
TEOREME
1. Suma gradelor nodurilor unui graf G=(V,M) cu n noduri şi m muchii este 2*m.
2. Pentru orice graf neorientat numărul nodurilor de grad impar este par.
3. Dacă graful neorientat G=(V,M) are n noduri, n>2, atunci cel putin 2 noduri au acelaşi grad. 9
4. Numărul total de grafuri neorientate cu n noduri este 2 la puterea n(n-1)/2.
5. Numărul de grafuri partiale ale unui graf cu m muchii este 2 la puterea m . 6. Numărul de subgrafuri ale unui graf nu n noduri este puterea n)-1
PROBLEME 10
(2 la
MATRICE ADIACENTA
Să se afişeze matricea de adiacentă a unui graf neorientat cu n noduri şi m muchii.
Se citesc de la tastatură numărul de noduri n şi numărul de muchii, după care se initializează matricea mat[i][j] cu 0 (zero). Se apelează functia citire(), care va citi de la tastatură muchiile grafului, după care se apelează functia afisare() care va afişa matricea de adiacentă.
#include
int mat[10][10],n,m;
void citire()
{int a,b,i,m;
for(i=1;i<=m;i++)
{cout<<"Dati muchia"<
cin>>a>>b;
mat[a][b]=mat[b][a]=1; } }
void afisare()
{int i,j;
cout<<"Matricea de adiacenta";
cout<
for(i=1;i<=n;i++)
{for(j=1;j<=n;j++)
cout<
cout<
void main()
{int i,j;
cout<<"n=";cin>>n;
cout<<"m=";cin>>m;
for(i=0;i
for(j=0;j
mat[i][j]=0;
citire();
afisare();
}
GRAF PARTIAL
Să se verifice dacă un graf P este graf partial al grafului G.
Cele două grafuri au n noduri şi sunt date prin matricile lor de adiacentă. Mai jos este o solutie posibilă a problemei. Se citesc cele două matrici de adiacentă cu ajutorul functiei citire. Functia verif() va verifica dacă matricea de adiacentă a grafului P are multimea muchiilor inclusă în multimea muchiilor grafului G.
#include
int n,a[10][10],b[10][10];
void citire(char c,int mat[10][10])
{int i,j;
for(i=1;i
for(j=i+1;j<=n;j++)
{cout<
cin>>mat[i][j];}
}
int verif()
{int i,j;
for(i=1;i
for(j=i+i;j<=n;j++)
if(a[i][j]
return 1;
}
void main()
{cout<<"dati n="; cin>>n;
cout<<"Dati elementele grafului G, dat prin matricea de adiacenta G"<
citire('G',a);
cout<<"Dati elementele grafului P, dat prin matricea de adiacenta
P"<
Gradele nodurilor
Să se verifice dacă valorile d1, d2, …, dn pot reprezenta gradele nodurilor unui graf neorientat cu n noduri.Mai jos este o solutie posibilă a problemei.
Se citesc gradele nodurilor grafului şi se introduc într-un vector, după care se calculează suma gradelor nodurilor (s) şi numărul nodurilor izolate (izolat). Functia verif() va returna zero dacă:
- suma s este impară (ştim că s=2*m) - mai mare decât n*(n-1) (ştim că s=n*(n-1) la un graf complet) - gradul oricărui vârf este mai mare sau egal decât numărul de noduri minus numărul de noduri izolate
Dacă functia verif() returnează zero, valorile date nu pot reprezenta gradele unui graf neorientat, altfel, pot reprezenta gradele unui graf neorientat.
#include
int n, d[10], s=0, izolat=0;
void citire()
{ int i;
for(i=1;i<=n;i++)
{ cout<<"d["<>d[i];
s=s+d[i];
if(d[i]==0)
izolat=izolat+1;
} 14
}
int verif()
{ if(s%2!=0||s>n*(n-1))
return 0;
else
{
for(int i=1;i<=n;i++)
if(d[i]>=n-izolat)
return 0;
return 1;
}
}
void main()
{ cout<<"n=";cin>>n;
citire();
if(verif()==1)
cout<<"valorile date pot reprezenta gradele unui graf";
else
cout<<"valorile date NU pot reprezenta gradele unui graf";
}
15
Noduri izolate
Să se afişeze numărul de noduri izolate ale unui graf G, dat prin matricea de adiacentă.Mai jos este o solutie posibilă a problemei.
Se citeşte matricea de adiacentă cu ajutorul functiei citire(). Functia verif() va verifica dacă suma elementelor matricei pe fiecare linie este diferită de zero şi va calcula câte sume sunt egale cu zero în variabila globală izolat care va retine numărul de noduri izolate.
#include
int n,mat[10][10], izolat=0;
void citire()
{int i,j;
for(i=1;i
for(j=i+1;j<=n;j++)
{cout<<"mat["<
cin>>mat[i][j];
mat[j][i]=mat[i][j];}
}
int verif()
{int i,j,s;
for(i=1;i<=n;i++) 16
{ s=0;
for(j=1;j<=n;j++)
s=s+mat[i][j];
if(s==0)
izolat++;
}
if(izolat==0) return 0; else return 1;
}
void main()
{cout<<"dati n="; cin>>n;
cout<<"Dati elementele grafului G, dat prin matricea de adiacenta G"<
citire();
if(verif()==1)
cout<<"Graful G contine "<
else
cout<<"Graful G NU contine noduri izolate";
}
17
Ciclu elementar
Să se afişeze dacă o secventă dată de noduri poate reprezenta un ciclu elementar, ştiind că graful este dat prin matricea de adiacentă. Mai jos
este o solutie posibilă a problemei.
Se citeşte matricea de adiacentă cu ajutorul functiei citire_matrice() şi secventa de noduri într-un vector v[i], cu ajutorul functiei citire_sir().
Functia ciclu() verifică:
° dacă primul element din şir corespunde cu ultimul element, pentru a fi ciclu
° dacă există muchie între oricare două elemente consecutive ale şirului
° dacă muchiile sunt distincte
Functia ciclu_elementar() verifică dacă elementele şirului sunt distincte cu exceptia primului şi a ultimului element.
Din functia main() se verifică prima dată şirul de elemente cu functia ciclu(), pentru a testa dacă şirul formează un ciclu, după care se verifică cu ajutorul functiei ciclu_elementar(), pentru a testa dacă şirul dat este ciclu elementar.
#include
int mat[10][10], v[10], n, nr;
void citire_matrice()
{int i,j;
for(i=1;i
for(j=i+1;j<=n;j++)
{cout<<"mat["<
cin>>mat[i][j]; 18
mat[j][i]=mat[i][j];}
}
void citire_sir()
{ int i;
for(i=1;i<=nr;i++)
{cout<<"v["<>v[i];}
}
int ciclu(int x)
{int i,j;
if(v[x]!=v[1])
return 0;
for(i=1;i
if(mat[v[i]][v[i+1]]==0)
return 0;
for(i=1;i
for(j=i+1;j
if(v[i]==v[j]&&v[i+1]==v[j+1]||v[i]==v[j+1]&&v[i+1]==v[j])
return 0;
return 1; }
int ciclu_elementar(int x)
{int i,j;
for(i=1;i
for(j=i+1;j<=x;j++)
if(v[i]==v[j])
return 0;
return 1;
}
void main()
{cout<<"dati n="; cin>>n;
cout<<"Dati elementele grafului G, dat prin matricea de adiacenta G"<
citire_matrice();
cout<<"Dati numarul de elemente=";cin>>nr;
citire_sir();
if(ciclu(nr)==1)
if(ciclu_elementar(nr-1))
cout<<"sirul dat este ciclu elementar";
else
cout<<"sirul dat este ciclu neelementar";
else
cout<<"sirul dat nu este ciclu";
}
Graf complet
20
Să se verifice dacă un graf dat prin matricea de adiacentă este graf complet şi să se afişeze un mesaj corespunzător. Mai jos este o solutie
posibilă a problemei.
Se citeşte matricea de adiacentă cu ajutorul functiei citire(). Functia graf_complet() verifică dacă deasupra diagonalei principale a matricii de adiacentă se află elemente egale cu zero, ştiind că zero înseamnă că nu există muchie între două noduri.
#include
int n, mat[10][10];
void citire()
{int i,j;
for(i=1;i
for(j=i+1;j<=n;j++)
{cout<<"mat["<>mat[i][j];
mat[j][i]=mat[i][j];}
}
int graf_complet()
{int i,j;
for(i=1;i
for(j=i+1;j<=n;j++)if(mat[i][j]==0)
return 0;
return 1;
}
21
void main()
{ cout<<"n=";cin>>n;
citire();
if(graf_complet()==1)
cout<<"graful dat prin matricea de adiacenta este complet";
else
cout<<"graful dat prin matricea de adiacenta NU este complet";
}
Graf conex
Să se verifice dacă un graf dat prin matricea de adiacentă este graf conex şi să se afişeze un mesaj corespunzător.
#include
int mat[10][10],n,v[10];
void citire()
{ int i,j;
for(i=1;i
for(j=i+1;j<=n;j++)
{cout<<"mat["<
cin>>mat[i][j]; 22
mat[j][i]=mat[i][j];
}
}
void parcurg(int x)
{ int i;
v[x]=1;
for(i=1;i<=n;i++)
if(mat[x][i]&&v[i]==0)
parcurg(i); }
int conex()
{ int i;
parcurg(1);
for(i=1;i<=n;i++)
if(v[i]==0)
return 0;
return 1;
}
void main()
{cout<<"n="; cin>>n;
citire();
if(conex()==1)
cout<<"Graful dat este conex"; 23
else
cout<<"Graful dat NU este conex";
}
Parcurgerea in adancime
Se citeşte matricea de adiacentă a unui graf neorientat. Să se afişeze nodurile grafului pentru parcurgerea în adâncime, pornind de la un nod citit de la tastatură.
#include
int v[10],n,mat[10][10];
void citire_matrice()
{ int i,j;
for(i=1;i
for(j=i+1;j<=n;j++)
{ cout<<"mat["<
cin>>mat[i][j];
mat[j][i]=mat[i][j];
}
}
void adancime(int n1)
{ int k;
cout<
v[n1]=1;
for(k=1;k<=n;k++)
if(mat[n1][k]==1&&v[k]==0)
adancime(k);
}
void main()
{ int n1;
cout<<"n=";cin>>n;
citire_matrice();
cout<<"Dati nodul de pornire=";cin>>n1;
adancime(n1);
}
Parcurgerea In
latime
Se citeşte matricea de adiacentă a unui graf neorientat. Să se afişeze nodurile grafului pentru parcurgerea în lătime, pornind de la un nod citit de la tastatură.
#include
int mat[10][10],n,n1,p,u,c[10],viz[10];
void citire_matrice()
{ int i,j;
for(i=1;i
for(j=i+1;j<=n;j++)
{ cout<<"mat["<
cin>>mat[i][j];
mat[j][i]=mat[i][j];
}}
void parcurg(int n1)
{ int i,j,l1;
p=u=1;
c[p]=n1;
viz[n1]=1;
while(p<=u)
{l1=c[p];
for(i=1;i<=n;i++)
if(mat[l1][i]&&!viz[i])
{viz[i]=1;
u++;
c[u]=i;;}
p++;} }
void main()
{int i;
cout<<"n=";cin>>n;
26
citire_matrice();
cout<<"Dati nodul de pornire=";cin>>n1;
parcurg(n1);
for(i=1;i<=n;i++)
cout<
cout<
Bibliografie
http://info-cniv.wikispaces.com
http://facultate.regielive.ro
http://www.graf.go.ro/index1.html http://ro.wikipedia.org/wiki/Graf http://ro.wikipedia.org/wiki/Programare_orientat%C4%83_pe_obiecte http://www.aut.upt.ro/~dberian/Labs/POO.pdf
27