Sunteți pe pagina 1din 15

Grafuri neorientate

n practic am ntlnit diferite tipuri de probleme precum: 1. aflarea celui mai scurt drum dintre dou orae 2. parcurgerea unui traseu printr-un anumit numr de localiti 3. se dau n persoane i relaia de prietenie dintre ele, s se afle dac persoana x este prieten cu persoana y 4. se consider un labirint sub forma unei matrici, s se determine traseul parcurs pe un drum minim pentru a ajunge n punctul (xa, yb) Aceste tipuri de probleme se pot reprezenta grafic n modul urmtor: oraele (1) sau persoanele (3) sunt reprezentate prin noduri iar o stad (1) sau relaia dintre dou persoane (3) este reprezentat printr-un segment de dreapt pe care l numim muchie. Cazul 1 se poate reprezenta grafic precum n figura 1.a. dac nlocuim oraele cu noduri i strzile cu michii, aceeai problem o putem reprezenta ca n figura 1.b.
Braov
1

Trgovite Piteti

Ploieti
2

4 3

Bucureti

Figura 1.a. Orae

Figura 1.b. Graf neorientat

Definiie Un graf neorientat este o pereche ordonat de mulimi (V, M), unde: V={v1, v2, v3, , vn} este o mulime finit i nevid de elemente, numite noduri sau vrfuri, iar M este o mulime finit de perechi neordonate, distincte, de elemente din V, de forma (vi, vj) unde ij i vi, vjV. Pentru exemplul din figura 1.b. avem: V={1, 2, 3, 4, 5}, mulimea nodurilor i M={(1,2), (1,4), (2,5), (3,5), (4,5)}, mulimea muchiilor OBS Muchia m=(1,2) are extremitile 1 i 2, iar nodurile 1 i 2 sunt adiacente. Vom spune c muchia m este incident cu nodurile 1 i 2 iar muchiile care au o extremitate comun se numesc incidente. Definiie Gradul unui nod X reprezint numrul de muchii incidente cu nodul X i l notm cu d(x). Un nod X al unui graf neorientat G=(V,M) se numete nod izolat dac are gradul zero. Un nod X al unui graf neorientat G=(V,M) se numete nod terminal dac are gradul unu. Exemple Nod terminal este nodul 3 din graful neorientat din Figura 1.b. iar d(3)=1. Nod izolat este nodul 6 din graful G=(V,M) din Figura 2.a. iar d(6)=0 Pentru graful din Figura 1.b. gradele nodurilor sunt: d(1)=2, d(2)=2, d(3)=1, d(4)=2, d(5)=3 Prof. Diaconu Diana Elena 1

Graf parial
Definiie Un graf neorientat Gp=(V,Mp) este graf parial al unui graf G=(V,M) dac MpM. Graful parial Gp=(V,Mp) se obine prin eliminarea uneia sau mai multor muchii din graful G=(V,M). Considerm graful G=(V,M) din figura 2.a. Dac din acest graf eliminm muchiile (1,4) i (3,4), obinem graful parial Gp=(V,Mp) din figura 2.b.
1 6 6

4 3 2 2 3

Figura 2.a. Graful G=(V,M)

Figura 2.b. Graful parial Gp=(V,Mp)

Subraf
Definiie Un graf neorientat Gs=(Vs,Ms) este subgraf al unui graf G=(V,M) dac MsM i VsV. Subgraful Gs=(Vs,Ms) se obine prin eliminarea uneia sau mai multor noduri din graful G=(V,M) i a tuturor muchiilor incidente cu acestea. Considerm graful G=(V,M) din figura 3.a. Dac din acest graf eliminm vrful 3 i toate muchiile incidente cu acest vrf, obinem subgraful Gs=(Vs,Ms) al grafului G=(V,M), din figura 3.b.
1 1
6
6

3
2

4 2

Figura 3.a. Graful G=(V,M) Figura 3.b. Subgraful Gs=(Vs,Ms) Teoreme 1. Suma gradelor nodurilor unui graf G=(V,M) cu n noduri i m muchii este 2*m. 2. Pentru orice graf neorientat numrul nodurilor de grad impar este par. 3. Dac graful neorientat G=(V,M) are n noduri, n>2, atunci cel puin 2 noduri au acelai grad. 4. Numrul total de grafuri neorientate cu n noduri este 5. Numrul de grafuri pariale ale unui graf cu m muchii este 2m 6. Numrul de subgrafuri ale unui graf nu n noduri este 2n-1. Prof. Diaconu Diana Elena 2

Reprezentarea grafurilor cu ajutorul matricei de adiacen Definiie Matricea de adiacen a unui graf G=(V,M) cu n noduri este o matrice ptratic de dimensiune nxn, completat cu 1 i 0, dup formula urmtoare: Ai,j= 1, dac (i,j)M 0, dac (I,j)M OBS Diagonala principal a matricei de adiacen are toate elementele egale cu 0 Suma elementelor de pe linia x sau coloana x reprezint gradul nodului x Matricea de adiacen a unui graf neorientat este simetric fa de diagonala principal Pentru nodul izolat x, sumele elementelor de pe linia x i de pe coloana x sunt egale cu zero. Exemplu S se afieze matricea de adiacen a unui graf neorientat cu n noduri i m muchii. Mai jos este o soluie posibil a problemei. Se citesc de la tastatur numrul de noduri n i numrul de muchii, dup care se iniializeaz matricea mat[i][j] cu 0 (zero). Se apeleaz funcia citire(), care va citi de la tastatur muchiile grafului, dup care se apeleaz funcia afisare() care va afia matricea de adiacen. #include<iostream.h> int mat[10][10],n,m; void citire() {int a,b,i,m; for(i=1;i<=m;i++) {cout<<"Dati muchia"<<i<<"="; cin>>a>>b; mat[a][b]=mat[b][a]=1; } } void afisare() {int i,j; cout<<"Matricea de adiacenta"; cout<<endl; for(i=1;i<=n;i++) {for(j=1;j<=n;j++) cout<<mat[i][j]<<" "; cout<<endl; } } void main() {int i,j; cout<<"n=";cin>>n; cout<<"m=";cin>>m; for(i=0;i<n;i++) for(j=0;j<n;j++) mat[i][j]=0; citire(); afisare(); } Prof. Diaconu Diana Elena Pentru n=4, m=3 i graful din figura 4.a, se afieaz matricea din figura 4.b.
3 2

Figura 4.a. Graf neorientat 0 1 1 0 1 0 1 0 1 1 0 0 0 0 0 0

Figura 4.b. Matricea de adiacen

Exemplu S se verifice dac un graf P este graf parial al grafului G. Cele dou grafuri au n noduri i sunt date prin matricile lor de adiacen. Mai jos este o soluie posibil a problemei. Se citesc cele dou matrici de adiacen cu ajutorul funciei citire. Funcia verif() va verifica dac matricea de adiacen a grafului P are mulimea muchiilor inclus n mulimea muchiilor grafului G. #include<iostream.h> int n,a[10][10],b[10][10]; void citire(char c,int mat[10][10]) {int i,j; for(i=1;i<n;i++) for(j=i+1;j<=n;j++) {cout<<c<<"["<<i<<"]["<<j<<"]="; cin>>mat[i][j];} } int verif() {int i,j; for(i=1;i<n;i++) for(j=i+i;j<=n;j++) if(a[i][j]<b[i][j]) return 0; return 1; } void main() {cout<<"dati n="; cin>>n; cout<<"Dati elementele grafului G, dat prin matricea de adiacenta G"<<endl; citire('G',a); cout<<"Dati elementele grafului P, dat prin matricea de adiacenta P"<<endl; citire('P',b); if(verif()) cout<<"Graful P este graf partial al grafului G"; }

Prof. Diaconu Diana Elena

Exemplu S se verifice dac valorile d1, d2, , dn pot reprezenta gradele nodurilor unui graf neorientat cu n noduri Mai jos este o soluie posibil a problemei. Se citesc gradele nodurilor grafului i se introduc ntr-un vector, dup care se calculeaz suma gradelor nodurilor (s) i numrul nodurilor izolate (izolat). Funcia verif() va returna zero dac: - suma s este impar (tim c s=2*m) - mai mare dect n*(n-1) (tim c s=n*(n-1) la un graf complet) - gradul oricrui vrf este mai mare sau egal dect numrul de noduri minus numrul de noduri izolate Dac funcia verif() returneaz zero, valorile date nu pot reprezenta gradele unui graf neorientat, altfel, pot reprezenta gradele unui graf neorientat. #include<iostream.h> int n, d[10], s=0, izolat=0; void citire() { int i; for(i=1;i<=n;i++) { cout<<"d["<<i<<"]=";cin>>d[i]; s=s+d[i]; if(d[i]==0) izolat=izolat+1; } } 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"; }

Prof. Diaconu Diana Elena

Exemplu S se afieze numrul de noduri izolate ale unui graf G, dat prin matricea de adiacen. Mai jos este o soluie posibil a problemei. Se citete matricea de adiacen cu ajutorul funciei citire(). Funcia verif() va verifica dac suma elementelor matricei pe fiecare linie este diferit de zero i va calcula cte sume sunt egale cu zero n variabila global izolat care va reine numrul de noduri izolate. #include<iostream.h> int n,mat[10][10], izolat=0; void citire() {int i,j; for(i=1;i<n;i++) for(j=i+1;j<=n;j++) {cout<<"mat["<<i<<"]["<<j<<"]="; cin>>mat[i][j]; mat[j][i]=mat[i][j];} } int verif() {int i,j,s; for(i=1;i<=n;i++) { 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"<<endl; citire(); if(verif()==1) cout<<"Graful G contine "<<izolat<<" noduri izolate"; else cout<<"Graful G NU contine noduri izolate"; }

Prof. Diaconu Diana Elena

Lan
Definiie Se numete lan, o secven de noduri ale unui graf neorientat G=(V,M), cu proprietatea c oricare dou noduri consecutive sunt adiacente. Lungimea unui lan este dat de numrul de muchii din care este format. Se numete lan elementar un lan care conine numai noduri distincte. Se numete lan simplu un lan care conine numai muchii distincte. Se numete lan compus un lan care nu este format numai din muchii distincte.

Ciclu
Definiie Se numete ciclu, un lan n care primul nod coincide cu ultimul i muchiile sunt distincte dou cte dou. Se numete ciclu elementar un ciclu care este format doar din noduri distincte, excepie fcnd primul i ultimul nod. Exemple Fie graful G=(V,M) din Figura 5, unde V={1, 2, 3, 4, 5, 6} este mulimea nodurilor i M={(1,2), (1,3), (1,4), (1,5), (2,3), (2,6), (3,4), (5,6)} este mulimea muchiilor Exemplu de lan elementar este L1={6,5,1,2,3} Exemplu de lan simplu este L2={2,6,5,1} Exemplu de lan compus este L3={3,1,5,6,2,1,3} Exemplu de ciclu este C1={1,3,4,1,2,6,5,1} Exemplu de ciclu elementar este C2={1,2,3,1}

3 2

6 4

Figura 5. Graful G=(V,M)

Exemplu S se afieze dac o secven dat de noduri poate reprezenta un ciclu elementar, tiind c graful este dat prin matricea de adiacen. Mai jos este o soluie posibil a problemei. Se citete matricea de adiacen cu ajutorul funciei citire_matrice() i secvena de noduri ntr-un vector v[i], cu ajutorul funciei citire_sir(). Funcia 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 Funcia ciclu_elementar() verific dac elementele irului sunt distincte cu excepia primului i a ultimului element. Din funcia main() se verific prima dat irul de elemente cu funcia ciclu(), pentru a testa dac irul formeaz un ciclu, dup care se verific cu ajutorul funciei ciclu_elementar(), pentru a testa dac irul dat este ciclu elementar.

Prof. Diaconu Diana Elena

#include<iostream.h> int mat[10][10], v[10], n, nr; void citire_matrice() {int i,j; for(i=1;i<n;i++) for(j=i+1;j<=n;j++) {cout<<"mat["<<i<<"]["<<j<<"]="; cin>>mat[i][j]; mat[j][i]=mat[i][j];} } void citire_sir() { int i; for(i=1;i<=nr;i++) {cout<<"v["<<i<<"]="; cin>>v[i];} } int ciclu(int x) {int i,j; if(v[x]!=v[1]) return 0; for(i=1;i<x;i++) if(mat[v[i]][v[i+1]]==0) return 0; for(i=1;i<x-1;i++) for(j=i+1;j<x;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<x;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"<<endl; 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"; }

Prof. Diaconu Diana Elena

Grafuri speciale
Definiie Graful G=(V,M) se numete graf nul dac mulimea M este vid, adic graful nu are muchii. Pentru graful nul din Figura 6 avem: V={1,2,3} M= Definiie Prin graf complet se nelege un graf neorientat n care oricare dou noduri sunt adiacente. Pentru graful complet din Figura 7 avem: V={1,2,3,4} M={(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)} Teorem Numrul de muchii al unui graf complet este Exemplu S se verifice dac un graf dat prin matricea de adiacen este graf complet i s se afieze un mesaj corespunztor. Mai jos este o soluie posibil a problemei. Se citete matricea de adiacen cu ajutorul funciei citire(). Funcia graf_complet() verific dac deasupra diagonalei principale a matricii de adiacen se afl elemente egale cu zero, tiind c zero nseamn c nu exist muchie ntre dou noduri. #include<iostream.h> int n, mat[10][10]; void citire() {int i,j; for(i=1;i<n;i++) for(j=i+1;j<=n;j++) {cout<<"mat["<<i<<"]["<<j<<"]=";cin>>mat[i][j]; mat[j][i]=mat[i][j];} } int graf_complet() {int i,j; for(i=1;i<n;i++) for(j=i+1;j<=n;j++)if(mat[i][j]==0) return 0; return 1; } 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"; } Prof. Diaconu Diana Elena

2 3

Figura 6. Graf nul

2 3

1
4

Figura 7. Graf complet

Definiie Un graf G=(V,M) se numete bipartit dac exist dou mulimi V1 i V2, astfel nct V=V1V2 i V1 V2= i orice muchie din mulimea M are o extremitate n mulimea de noduri V1 i o alt extremitate n mulimea de noduri V2. Graful din Figura 8 este bipartit i conine: V={1, 2, 3, 4, 5, 6, 7} M={(1,5),(1,6),(2,3),(2,4),(7,6)} V1={1,2,7} i V2={3,4,5,6}

3 4

1
6 7

Figura 8. Graf bipartit Exemplu S se verifice dac un graf dat prin matricea de adiacen este graf bipartit i s se afieze un mesaj corespunztor. Mai jos este o soluie posibil a problemei. #include<iostream.h> int mat[10][10],n,m,viz[10]; void citire_matrice() { int i,j; for(i=1;i<n;i++) for(j=i+1;j<=n;j++) { cout<<"mat["<<i<<"]["<<j<<"]="; cin>>mat[i][j]; mat[j][i]=mat[i][j]; } } int bipart(int v) { int p,u,i,c[10],k; p=1;u=1;viz[v]=1;c[p]=v; while(p<=u) { k=c[p]; for(i=1;i<=n;i++) if(mat[k][i]) if(viz[i]==0) {c[++u]=i; viz[i]=3-viz[k]; } else if(viz[k]==viz[i]) return 0; p++; } return 1; } int primul() {int i; for(i=1;i<=n;i++) if(viz[i]==0) return i; return 0; } Prof. Diaconu Diana Elena 10

void main() { int v,i,j; cout<<"n=";cin>>n; cout<<"m=";cin>>m; citire_matrice(); do { v=primul(); } while(v && bipart(v)); if(v==0) { cout<<"Graful dat este bipartit "; for(i=1;i<=2;i++) {cout<<"\nMultimea "<<i<<"={"; for(j=1;j<=n;j++) if(viz[j]==i) cout<<j<<" "; cout<<"}"; } } else cout<<"Graful dar NU este bipartit"; } Definiie Graful bipartit G=(V,M) se numete graf bipartit complet dac pentru orice nod vi care aparine lui V1 i orice nod vj care aparine lui V2, exist o muchie format din cele dou noduricare aparine mulimii M([vi ,vj]M) Graful din Figura 9 este bipartit complet i conine: V={1,2,3,4,5,6} M={(1,3),(1,4),(1,5),(1,6),(2,3),(2,4),(2,5), (2,6)} V1={1,2} i V2={3,4,5,6}

3 4

1
6

Figura 9. Graf bipartit complet

Reprezentarea grafurilor cu ajutorul listelor de adiacen Definiie Listele de adiacen a unui graf G=(V,M) se construiesc cu ajutorul unei matrici n care pe fiecare linie se va memora lista vecinilor indicelui respectiv al linei. Pentru graful din Figura 10, avem: V={1,2,3,4,5,6} M={(1,3),(1,6),(2,3),(2,4),(2,6)} 1-> 3, 6 2-> 3, 4, 6 3-> 1, 2 4->2 5 6-> 1, 2 Prof. Diaconu Diana Elena

3 4

1
6

Figura 10. Graf

11

Graf conex
Definiie Graful G=(V,M) se numete graf conex dac pentru oricare dou noduri vi, vj V, exist un lan de la vi la vj. Pentru graful conex din Figura 11 avem: V={1,2,3,4,5} M={(1,3),(1,5),(2,3),(2,4),(2,5)} Se numete component conex a grafului G=(V,M), un subgraf conex al lui G, C=(V1,M1) cu proprietatea c nu exist nici un lan n G care s lege un nod din V1 cu un nod din V-V1.

3 4

1
5

Figura 11. Graf conex

Exemplu S se verifice dac un graf dat prin matricea de adiacen este graf conex i s se afieze un mesaj corespunztor. Mai jos este o soluie posibil a problemei. #include<iostream.h> int mat[10][10],n,v[10]; void citire() { int i,j; for(i=1;i<n;i++) for(j=i+1;j<=n;j++) {cout<<"mat["<<i<<"]["<<j<<"]="; cin>>mat[i][j]; 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"; else cout<<"Graful dat NU este conex"; } Prof. Diaconu Diana Elena 12

Parcurgerea grafurilor
Definiie Parcurgerea grafurilor reprezint modalitatea de vizitare a nodurilor acestuia. Exist mai multe modaliti de parcurgere a grafurilor. Mai departe vom studia parcurgerea n lime i parcurgerea n adncime.

1. Parcurgerea n lime (BF breadth first) Descriere Parcurgerea n lime se realizeaz prin vizitarea nodurilor grafului G=(V,M), n urmtoarea 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 i2pn la ik - se ncheie parcurgerea dup ce se parcurg toate nodurile grafului De exemplu, pentru graful din Figura 12.a, parcurgerea n lime este: - din nodul 1 -> 2, 3, 4, 5 - din nodul 2 -> 1, 3, 5, 4 - din nodul 3 -> 1, 2, 4, 5 OBS Parcurgerea n lime depinde de ordinea de parcurgere a nodurilor adiacente.

1 3

4
5

Figura 12.a. Graf

Exemplu Se citete matricea de adiacen a unui graf neorientat. S se afieze nodurile grafului pentru parcurgerea n lime, pornind de la un nod citit de la tastatur. Mai jos este o soluie posibil a problemei. #include<iostream.h> int mat[10][10],n,n1,p,u,c[10],viz[10]; void citire_matrice() { int i,j; for(i=1;i<n;i++) for(j=i+1;j<=n;j++) { cout<<"mat["<<i<<"]["<<j<<"]="; 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; Prof. Diaconu Diana Elena 13

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; citire_matrice(); cout<<"Dati nodul de pornire=";cin>>n1; parcurg(n1); for(i=1;i<=n;i++) cout<<c[i]<<" "; cout<<endl; }

1. Parcurgerea n adncime (DF depth first) Descriere Parcurgerea n adncime se realizeaz prin vizitarea nodurilor grafului G=(V,M), n urmtoarea ordine: - se viziteaz nodul i - se viziteaz primul nod adiacent cu el, nc nevizitat, dup care urmtorul nod adiacent cu el i tot aa pn cnd nu mai are noduri adiacente cu el nevizitate - se revine la nodul I i se reiau paii - se ncheie parcurgerea dup ce se parcurg toate nodurile grafului De exemplu, pentru graful din Figura 12.b, parcurgerea n adncime este: - din nodul 1 -> 2, 3, 5, 4 - din nodul 2 -> 1, 3, 4, 5 - din nodul 3 -> 1, 2, 5, 4 OBS Parcurgerea n adncime depinde de ordinea de selecie a nodurilor adiacente.

1 3

4
5

Figura 12.b Graf

Exemplu Se citete matricea de adiacen a unui graf neorientat. S se afieze nodurile grafului pentru parcurgerea n ladncime, pornind de la un nod citit de la tastatur. Mai jos este o soluie posibil a problemei. #include<iostream.h> int v[10],n,mat[10][10];

Prof. Diaconu Diana Elena

14

void citire_matrice() { int i,j; for(i=1;i<n;i++) for(j=i+1;j<=n;j++) { cout<<"mat["<<i<<"]["<<j<<"]="; cin>>mat[i][j]; mat[j][i]=mat[i][j]; } } void adancime(int n1) { int k; cout<<n1<<" "; 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); }

Prof. Diaconu Diana Elena

15

S-ar putea să vă placă și