Sunteți pe pagina 1din 16

GRAFURI

A. Grafuri neorientate Definitie: Se numeste graf neorientat o pereche de multimi G = (A,B) in care A este multimea nodurilor (este finita si nevida) si B e multimea relatiilor/muchiilor. G1: A = {1,2,3,4,5} B = {(1,2),(1,3),(2,3),(2,5)} B. Grafuri orientate (digrafuri) Se numeste graf orientat o multime ordonata (A,B) in care A este multimea nodurilor (finita si nevida), iar B este multimea arcelor. G2: A = {1,2,3,4,5} B = {(1,2),(2,1),(2,3),(3,1),(5,2)} Terminologie Daca (x,y) apartine de B atunci: - x si y sunt noduri adiacente - x si y sunt extremitatile arcului (x,y) y sunt incidente cu (x,y) cazul grafurilor orientate: - x este extremitatea initiala a (x,y) extremitatea finala a (x,y) u si v sunt incidente Exemplu: - 1 este adiacent cu 2 si 3 - 1 si 2 sunt extremitatile (1,2) - nodul 1 este incident cu (1,2) - (5,2) si (2,3) sunt incidente Gradul unui nod: numarul de muchii incidente cu el nodului x G2: d(1) = 3 Pentru grafurile orientate, se definesc: Gradul exterior al lui x: d+(x) = numarul arcelor care pleaca din x interior al lui x: d-(x) = numarul arcelor care intra in x Exemplu: pentru G2: d(1)=3; d+(1)=1; d-(1)=2; d(x) - gradul G1: d(1) = 2

- x si - in - y este u = (x,y); v = (y,z); =>

Gradul

Nodurile de grad 0 se numesc noduri izolate. Nodurile de grad 1 se numesc noduri terminale. Proprietati 1. 2. 3. d+(x) + d-(x) = d(x) Daca un graf are m muchii sau arce atunci: d(x1) + d(x2) + ... + d(xn) = 2m Daca un graf orientat are m arce: o d+(x1) + d+(x2) + ... + d+(xn) = m o d-(x1) + d-(x2) + ... + d-(xn) = m

Lanturi. Drumuri A. Pentru grafuri neorientate Se numeste lant o succesiune de noduri x1 ... xk, cu proprietatea ca oricare doua noduri vecine (xi,xi+1) apartin de B. x1, xk sunt extremitatile lantului. Lungimea

lantului este egala cu numarul de muchii care il compun, k-1. lant sunt distincte, atunci lantul este elementar. G3: 1,2,3,1,4 - Lant neelementar (lungime 4) 1,2,3,4 - Lant elementar (lungime 3) 1,2,3,1,2,5 - Lant neelementar (lungime 5)

Daca nodurile din

B. Pentru grafuri orientate Se numeste lant o succesiune de arce u1, u2 ... uk, cu proprietatea ca oricare doua arce de pe pozitii consecutive au un nod comun. Observatie: nu conteaza ordinea de parcurgere Se numeste drum o succesiune de noduri x1, x2 ... xk cu proprietatea ca (xi,xi+1) este arc. Observatie: conteaza ordinea de parcurgere Daca nodurile sunt distincte, drumul se numeste elementar G4: Lanturi: (1,2),(2,3),(3,4) Drumuri: 1,2,3,1,2 - Drum neelementar Drum elementar (1,2),(5,2),(2,3) 1,2,3,4 -

Cicluri. Circuite A. Pentru grafuri neorientate Se numeste ciclu intr-un graf neorientat un lant x1,x2 ... xk si oricare 2 muchii (xi,xi+1) sunt distincte. Daca un ciclu are toate nodurile distincte 2 cate 2 cu exceptia capetelor, atunci el se numeste ciclu elementar. G5: 1,2,3,4,1 - Ciclu elementar - Ciclu elementar Ciclu neelementar 2,3,4,1,2 1,2,3,4,2,5,1 -

B. Pentru grafuri orientate Se numeste circuit intr-un graf un drum x1,x2 ... xk cu proprietatea ca x1 = xk si arcele (xi,xi+1) sa fie distincte 2 cate 2. Un circuit in care toate nodurile sunt distincte cu exceptia capetelor se numeste circuit elementar. G6: 1,2,3,1 - Circuit elementar 2,3,1,2 - Circuit elementar 2,1,2,3,1,5,2 - Circuit neelementar Reprezentarea grafurilor in memorie 1. 2. 3. 4. Reprezentarea prin matrice de adiacenta Liste de adiacenta Vector de muchii Matrice arce-noduri 01111 10111 11010 11100 11000 01001 10100 10010 00000 01000

1. Matricea de adiacenta A.Pentru grafuri neorientate a[i,j] = 1, daca intre i si j este muchie a[i,j] = 0 altfel.

Observatie: Pe diagonala principala toate elementele sunt 0 (nu avem bucle). Matricea este simetrica fata de diagonala principala, deci: a[i,j] = a[j,i]. B. Pentru grafuri orientate a[i,j] = 1, daca exista arcul (i,j); a[i,j] = 0, altfel.

2. Liste de adiacenta Pentru fiecare nod se memoreaza o lista a vecinilor sai. intregul graf este necesar un vector de liste (P) in care Pi este adresa primului element al listei asociate lui i. Nod Lista de adiacenta 1 2 3 4 5 2,3,5 1,3 1,2 1 G 7:

Pentru

Nod Lista de adiacenta 1 2 3 4 5 2,3 1,3 2 1

G 8:

Observatie: pentru grafurile orientate se memoreaza in lista lui i nodurile k pentru care exista arcul (i,k). struct elem { int nod; elem *next; }; elem *p[100]; int n; 3. Vector de muchii struct muchie x,y; // capetele arcului v[100]; 4. Matricea noduri-arce Este folosita in special pentru grafurile orientate. G9: Matricea noduri-arce aferenta:

{int } int n,m;

Observatie: matricea noduri-arce poate fi adaptata si pentru grafurile neorientate.

Parcurgerea grafurilor
Parcurgerea unui graf presupune vizitarea (prelucrarea) nodurilor grafului, o singura data fiecare, intr-o anumita ordine. Nodurile vizitate sunt legate intre ele direct sau indirect. functie de ordinea relativa a nodurilor exista 2 metode de parcurgere: - Metoda parcurgerii pe nivele (pe latime) - Breadth First (BF) - Metoda parcurgerii in adancime - Depth First (DF) Metoda Breadth First Pentru grafuri neorientate G10: x = 1 Se porneste de la un nod oarecare x. nodului x daca nu au fost deja vizitati. anterior devine nod curent si este prelucrat la fel ca nodul x. Matrice de adiacenta (sau alte variante de reprezentare): a Coada (in care se memoreaza in ordinea parcursa nodurile vizitate): c o p, u - indicatorii primului si ultimului element din coada Vectorul nodurilor vizitate: v o v[i]=1, daca i a fost vizitat; o v[i]=0, altfel. int a[20][20],n; int v[20]; BF(int x){ c[20],p,u,i; p=u=0; c[p]=x; v[x]=1; cout<<c[p]<<" "; +) u++; v[i]=1; }p++; } } B. Pentru grafuri orientate Observatie: algoritmul se adapteaza astfel incat sa poata fi luati in considerare toti vecinii unui nod. G11: x = 1 1, 2, 3, 4, 5 int a[20][20],n; int v[20]; void BF(int x){ int c[20],p,u,i; p=u=0; c[p]=x; v[x]=1; while(p<=u){ cout<<c[p]<<" "; for(i=1;i<=n;i++) p]][i] || a[i][c[p]]) && !v[i]){ c[u]=i; v[i]=1; } p++; } } Metoda Depth First A. Pentru grafuri neorientate 1, 2, 3, 4, 6, 7, 8, 9, 5 Se viziteaza toti vecinii directi ai Fiecare dintre nodurile vizitate la pasul Structuri de date necesare pentru implementare sunt: In

A.

void int while(p<=u){ for(i=1;i<=n;i+ if(a[c[p]][i] && !v[i]){ c[u]=i;

if((a[c[ u++;

G12: x = 1 1, 2, 4, 5, 10, 9, 7, 8, 6, 3 Se porneste de la un nod oarecare x. Se alege primul vecin al lui x care nu a fost inca vizitat. Pentru nodul ales se reia procedeul. Daca un nod nu are nici un vecin nevizitat se revine la nodul vizitat anterior acestuia. Structuri de date necesare implementarii: - Matrice de adiacenta (sau alte variante): a - Stiva: s (in care se memoreaza nodurile in ordinea parcurgerii) Daca se implementeaza varianta recursiva se va folosi stiva procesorului - Vectorul nodurilor vizitate: v int a[20][20],u; int v[20]; void DF(int x){ cout<<x<<" "; v[x]=1; for(int i=1;i<=n;i++) [i] && !v[i]) } B. Pentru grafuri orientate G13: x = 10 4, 2, 1, 3, 6, 8, 7, 9 Parcurgerea este similara, punandu-se conditia de parcurgere a tuturor vecinilor unui nod indiferent de sens. 10,

if(a[x] DF(i);

Tipuri de grafuri
1. Graf partial Fie G=(A,B) si G1=(A1,B1). Spunem ca G1 este un graf partial al lui G daca A=A1 si B1 este inclus sau egal cu B. Un graf partial se obtine dintr-un graf, indepartand o parte dintre muchiile sale si pastrand toate nodurile acestuia. G14: Graful initial G15: Graful partial

2. Subgraful unui graf G=(A,B) si G1=(A1,B1); egal cu A; B1 inclus sau egal cu B. apartine A1 daca (x,y) apartine de B => (x,y) apartine de B1} selectand o parte din nodurile sale si o parte din nodurile adiacente cu acesta. G16: Graful initial

Fie A1 inclus sau B1 = {(x,y) / oricare x,y Subgraful se obtine din graful initial

G17

Subgraful

3.

4.

Graf complet Un graf este complet daca oricare doua varfuri distince sunt adiacente. G18: Un graf neorientat cu n noduri are n(n-1)/2 muchii. Exista un singur graf complet neorientat cu n noduri. Exista mai multe grafuri orientate complete cu n noduri. Grafuri bipartite Fie G=(A,B) neorientat. G este bipartit daca exista doua multimi, A1 si A2 astfel incat A1 A2 = si A1 U A2 = A, iar oricare muchie (x,y) apartinand lui B are un capat in multimea A1 si celalalt in A2.

Un graf bipartit este bipartit complet daca fiecare nod din multimea A1 este adiacent cu nodurile din A2 si reciproc.

toate

5. Grafuri conexe Un graf este conex daca este format dintr-un singur nod sau daca intre oricare doua noduri ale sale exista cel putin un lant. A. Pentru grafuri neorientate B. Pentru grafuri orientate

Se numeste componenta conexa a unui graf un sungraf al sau care este conex si care este maximal in raport cu aceasta proprietate (daca i se adauga un nod isi pierde aceasta proprietate). Observatie: pentru grafurile orientate nu se tine cont de orientarea arcelor. 6. Grafuri tare conexe Un graf este tare conex daca ar un singur nod sau daca oricare ar fi (x,y) exista drum de la x la y si exista drum de la y la x. Determinarea componentelor tare conexe Se poate realiza prin 3 metode: 1. 2. 3. Utilizand metoda DF/BF Utilizand matricea drumurilor Algoritmul +/O componenta tare conexa este un subgraf al sau care este tare conex si care este maximal in raport cu aceasta proprietate. Observatie: reunind toate arcele din componentele tare conexe se poate obtine o multime mai mica decat multimea arcelor grafului initial. Se poate construi un graf al componentelor tare conexe in care fiecare componenta tare conexa formeaza un nod iar arcele simuleaza legaturile dintre ele. Determinarea componentelor tare conexe utilizand matricea drumurilor d(i,j) = 1, daca exista drum de la i la j d(i,j) = 0, altfel

11010 11010 11111 11010 11111 Exista doi algoritmi: 1. DF; prin apelul DF(x) se obtin toate nodurile pentru care exista un drum care pleaca din x. Cu aceastea se poate completa linia x din matrice. 2. RoyWarshall Algoritmul Roy-Warshall int a[20][20], d[20][20]; void RoyWarshall(){ int i,j,k; for(i=1;i<=n;i++) for(j=1;j<=n;j+ +) d[i][j]=a[i][j]; for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(d[i][k] && d[k][j]) d[i][j]=1;} Observatie: daca se doreste determinarea unui drum intre nodurile x si y, in matricea drumurilor se vor trece nodurile intermediare determinate cu algoritmul Roy-Warshall (valorile k). Totodata, se va modifica si algoritmul de completare a matricei de adiacenta, asa cum este aratat in cele ce urmeaza: int a[20][20], d[20][20], n; void citire(){ int m,x,y; fstream f("graf.in",ios::in); f>>n>>m; for (int i=1;i<=m;i++){ f>>x>> y; a[x][y] = y; } }void RoyWarshall(){ int i,j,k; for(i=1;i<=n;i++) for(j=1;j<=n;j++) d[i][j]=a[i][j]; for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1 ;j<=n;j++) if(d[i] [k] && d[k][j]) if (!d[i][j]) d[i] [j]=k;} Determinarea efectiva se realizeaza cu metoda Divide et Impera. void drum(int x,int y){ if (x!=d[x][y] && y!=d[x][y]){ drum(x,d[x][y]); cout<<d[x][y]<<" "; drum(d[x] [y],y); }} 7. Grafuri hamiltoniene Lant hamiltonian: lant elementar care contine toate nodurile grafului. hamiltonian: ciclu elementar care contine toate nodurile grafului. hamiltonian: graf care contine un ciclu hamiltonian. Conditii de suficienta: Teorema lui Dirac: Fie G dat prin perechea (A,B). Daca G are un numar de cel putin 3 varfuri astfel incat gradul fiecarui nod respecta conditia d(x)n/2, atunci graful este hamiltonian. Algoritmi de determinare a unei solutii Algoritmul utilizat este Backtracking, care este adaptat in mod corespunzator 8. Grafuri euleriene Ciclu eulerian: ciclu care trece prin toate muchiile unui graf exact o data. eulerian: graf care contine cel putin un ciclu eulerian.

Ciclu Graf

Graf

Conditii de suficienta Teorema: Fie un graf conex fara noduri izolate cu n 3 noduri. Graful este eulerian daca si numai daca pentru oricare nod al sau, x, d(x) este par. Determinarea unui ciclu eulerian

Se porneste de la un nod oarecare si se construieste un ciclu. Se parcurg nodurile din ciclul determinat anterior; daca exista un nod care mai are neincluse in ciclul anterior se construieste un nou ciclu provenind de la acest nod. Ciclul construit este inclus in ciclul initial in locul nodului gasit la pasul anterior. o o o o o o o o o pas 1: c1: 1,2,3,1 c2: 2,4,7,2 pas 2: c1: 1,2,4,7,2,3,1 c2: 7,5,10,7 pas 3: c1: 1,2,4,7,5,10,7,2,3,1 c2: 7,8,11,7 pas 4: c1: 1,2,4,7,8,11,7,5,10,7,2,3,1 c2: 7,6,9,7 pas 5: c1: 1,2,4,7,6,9,7,8,11,7,5,10,7,2,3,1

muchii

Drumuri maxime/minime in graf Problemele de optim presupun ca fiecare muchie a grafului are asociat un anumit cost (de exemplu, distanta intre doua orase, i si y). Aceste informatii se memoreaza in matricea costurilor: c(i,j) = costul asociat muchiei (i,j); c(i,j) = +, daca nu exista muchia (i,j); Observatie: daca intereseaza, un drum maxim, in loc de + se memoreaza - sau o valoare adecvata. Exista mai multe tipuri de probleme de optim: 1. sursa unica/destinatii multiple 2. sursa multipla/destinatii multiple Algoritmi pentru drum minim cu sursa unica 1. Algoritmul lui Dijkstra 2. Algoritmul lui Lee Algoritmul lui Dijkstra Se considera un graf orientat in care fiecare arc are asociat un anumit cost. Dandu-se un nod x oarecare, se cere sa se determine drumurile de cost minim care pornesc de la nodul x si ajung la toate celelalte noduri ale grafului. Observatie: daca sunt mai multe noduri de acelasi cost minim intre x si y, se va gasi unul dintre ele. Observatie: metoda folosita este metoda Greedy. Se utilizeaza urmatoarele structuri: s - vectorul nodurilor selectate; s[i]=1, daca nodul i este selectat s[i]=0 altfel d d[i] = costul drumului minim de la x la y d[i]=+, daca nu exista drum de la x la i t - vectorul de "tati"; vectorul predecesorilor t[i]=predecesorul lui i in drumul de la x la i t[i]=0, daca nu exista drum

Exemple de probleme care se rezolva cu GRAFURI


1.Afisare ciclu eulerian
#include <fstream.h> #include <conio.h> struct elem{ int nod; elem *next;}; int a[20][20],n; elem *p1,*u1,*p2,*u2; void citire() { fstream f("graf.in",ios::in); int m,x,y; f>>n>>m; for (int i=1;i<=m;i++) { f>>x>>y;

a[x][y] = a[y][x] = 1; } f.close();} int vecin(int x) { int i; for (i=1;i<=n;i++) if (a[x][i]) return i; return 0;} void add(int x,elem *&p,elem *&u) { elem *q; q=new elem; q->nod = x; q->next = 0; if (u) u->next = q; else p=q; u=q;} void lista(int x,elem *&p,elem *&u) {int i; p=u=0; add(x,p,u); do{ i=vecin(u->nod); a[i][u->nod] = a[u->nod][i] = 0; add(i,p,u); }while(u->nod!=x);} elem *ramura() {for (elem *q=p1;q;q=q->next) if (vecin(q->nod)) return q; return 0;} void euler() { elem *q; lista(1,p1,u1); do{ q=ramura(); if (q) {lista(q->nod,p2,u2); u2->next = q->next; q->next = p2->next;} }while(q);} void afisare() { for (elem *q=p1;q;q=q->next) cout<<q->nod<<" ";} void main() {clrscr(); citire(); euler(); afisare(); getch(); }

2.Algoritmul lui Dijkstra


#include <fstream.h>

#include <conio.h> int s[20],d[20],t[20],c[20][20]; int n; const inf=10000; void citire() { fstream f("graf.in",ios::in); int m,x,y,t; f>>n>>m; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) c[i][j]=inf; for (i=1;i<=m;i++) {f>>x>>y>>t; c[x][y] = t; } } void dijkstra(int x) { int i,y,pas,min; //initializare for (i=1;i<=n;i++) {s[i]=0; d[i]=c[x][i]; if (d[i]!=inf) t[i]=x; else t[i]=0; }s[x]=1; t[x]=0; for (pas=1;pas<=n-2;pas++) {min = inf; y = 0; for (i=1;i<=n;i++) if (!s[i] && d[i]<min){ min=d[i]; y=i; } s[y]=1; for (i=1;i<=n;i++) if (!s[i] && c[y][i]!=inf) if (min+c[y][i]<d[i]) {d[i]=min+c[y][i]; t[i]=y; } } }void drum(int x,int y) {if (y!=0) {drum(x,t[y]); cout<<y<<" "; } }void main() {clrscr(); citire(); int x,y; cout<<"Nodurile intre care sa fie afisat drum: "; cin>>x>>y; dijkstra(x); drum(x,y); getch();} void citire() fstream f("graf.in",ios::in); int m,x,y; f>>n>>m; for (int i=1;i<=m;i++) f>>x>>y; a[x][y] = a[y][x] = 1; f.close();

3.Afisare componente conexe


#include <fstream.h> #include <conio.h> int n,v[20],a[20][20];

} void df(int x) { v[x]=1; cout<<x<<" "; for (int i=1;i<=n;i++) if (a[x][i] && !v[i]) df(i); } void comp() { int i,nr=0; for (i=1;i<=n;i++) if (!v[i]) { nr++; cout<<"Componenta conexa "<<nr<<": "; df(i); cout<<endl; } } void main() { clrscr(); citire(); comp(); getch(); }

int m,x,y; f>>n>>m; for (int i=1;i<=m;i++) { f>>x>>y; a[x][y] = 1; } f.close(); } void RoyWarshall() { int i,j,k; for (i=1;i<=n;i++) for (j=1;j<=n;j++) d[i][j] = a[i][j]; for (k=1;k<=n;k++) for (i=1;i<=n;i++) for (j=1;j<=n;j++) if (d[i][k] && d[k][j]) d[i][j]=1; } void comp() { int nc,x,i,c[20]; nc=0; for (x=1;x<=n;x++) c[x]=0; for (x=1;x<=n;x++) if (c[x]==0){ nc++; c[x]=nc; cout<<"Componenta tare conexa "<<nc<<": "<<x<<" "; for (i=1;i<=n;i++) if (d[x][i] && d[i][x]){ if (x!=i) cout<<i<<" "; c[i]=nc; } cout<<endl; } } void main() { clrscr(); citire(); RoyWarshall(); comp(); getch();} for (int j=1;j<=n;j++) c[i][j]=inf; for (i=1;i<=m;i++) { f>>x>>y>>t; c[x][y] = t; void lee(int x) {int i,j,ok,pc; //intializare for (i=1;i<=n;i++) { pas[i]=0; d[i]=inf;

4.Afisarea componentelor tare conexe


#include <fstream.h> #include <conio.h> int a[20][20],n,d[20][20]; void citire() { fstream f("graf.in",ios::in);

5.Algoritmul lui Lee


#include <fstream.h> #include <conio.h> int pas[20],d[20],t[20],c[20][20]; int n; const inf=10000; void citire() { fstream f("graf.in",ios::in); int m,x,y,t; f>>n>>m; for (int i=1;i<=n;i++)

} void drum(int x,int y) {if (y!=0) {drum(x,t[y]); cout<<y<<" "; } } void main() {clrscr(); citire(); int x,y; cout<<"Nodurile intre care sa fie afisat drum: "; cin>>x>>y; lee(x); drum(x,y); getch();}

t[i]=0; } pc=1; pas[x]=pc; d[x]=0; do {ok=1; for (i=1;i<=n;i++) if (pas[i]==pc) for (j=1;j<=n;j++) if (c[i][j]!=inf) if (d[i]+c[i][j]<d[j]) {d[j]=d[i]+c[i][j]; t[j]=i; pas[j]=pc+1; ok=0; } pc++; }while(!ok);

f>>n>>m; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (i!=j) c[i][j]=inf; for (i=1;i<=m;i++) {f>>x>>y>>t; c[x][y] = t; } } void RoyFloyd() {int i,j,k; for (k=1;k<=n;k++) for (i=1;i<=n;i++) if (c[i][k]!=inf && i!=k) for (j=1;j<=n;j++) if (c[k][j]!=inf && k!=j) if (c[i][k]+c[k][j]<c[i] [j]) {c[i][j]=c[i][j]+c[k][j]; t[i][j]=k; } } void drum(int x,int y) {if (t[x][y]) {drum(x,t[x][y]); cout<<t[x][y]<<" "; drum(t[x][y],y); } } void main() {clrscr(); citire(); RoyFloyd(); int x,y; cout<<"Nodurile intre care sa fie afisat drum: "; cin>>x>>y; if (c[x][y]!=inf) {cout<<x<<" "; drum(x,y); cout<<y; } getch(); }

6.Algoritmul Roy-Floyd
#include <fstream.h> #include <conio.h> int c[20][20],t[20][20]; int n; const inf=10000; void citire() {fstream f("graf.in",ios::in); int m,x,y,t;

7.Breadth First - Graf neorientat


#include <fstream.h> #include <conio.h> int a[20][20],n; int v[20]; void citire() { int m,x,y;

fstream f("graf.in",ios::in); f>>n>>m; for (int i=1;i<=m;i++) f>>x>>y; a[x][y] = a[y][x] = 1; f.close(); void bf(int x) int c[20],p,u,i; p=u=0;

c[p]=x; v[x]=1; while(p<=u) { cout<<c[p]<<" "; for (i=1;i<=n;i++) if (a[c[p]][i] && !v[i]){ u++; c[u]=i; v[i]=1; } p++; }

fstream f("graf.in",ios::in); f>>n>>m; for (int i=1;i<=m;i++) { f>>x>>y; a[x][y] = 1; } f.close(); } void bf(int x) { int c[20],p,u,i; p=u=0; c[p]=x; v[x]=1; while(p<=u) { cout<<c[p]<<" "; for (i=1;i<=n;i++) if ((a[c[p]][i] || a[i] [c[p]]) && !v[i]){ u++; c[u]=i; v[i]=1; } p++; } } void main() { int x; clrscr(); citire(); cout<<"Nodul de la care incepe parcurgerea: "; cin>>x; bf(x); getch(); }

void main() { int x; clrscr(); citire(); cout<<"Nodul de la care incepe parcurgerea: "; cin>>x; bf(x); getch(); }

Bre 8. Breadth First - Graf orientat


#include <fstream.h> #include <conio.h> int a[20][20],n; int v[20]; void citire() { int m,x,y;

9.Depth First - Graf neorientat


#include <fstream.h> #include <conio.h> int n,a[20][20],v[20]; void citire() { int m,x,y; fstream f("graf.in",ios::in); f>>n>>m; for (int i=1;i<=m;i++) { f>>x>>y;

a[x][y] = a[y][x] = 1; f.close(); void df(int x) v[x]=1; cout<<x<<" "; for (int i=1;i<=n;i++) if (a[x][i] && !v[i]) df(i); void main() clrscr();

citire(); int x; cout<<"Nodul de la care incepe parcurgerea: "; cin>>x; df(x); getch(); }

a[x][y] = 1; } f.close(); } void df(int x) { v[x]=1; cout<<x<<" "; for (int i=1;i<=n;i++) if ((a[x][i] || a[i][x]) && ! v[i]) df(i); } void main() { clrscr(); citire(); int x; cout<<"Nodul de la care incepe parcurgerea: "; cin>>x; df(x); getch(); } }

10.Depth First - Graf orientat


#include <fstream.h> #include <conio.h> int n,a[20][20],v[20]; void citire() { int m,x,y; fstream f("graf.in",ios::in); f>>n>>m; for (int i=1;i<=m;i++) { f>>x>>y;

11.Gradul nodurilor unui graf neorientat


#include <fstream.h> #include <conio.h> int a[10][10]; int m,n; int g[10]; void citire() { int i,j; fstream f("graf.in",ios::in); f>>m>>n; for (int k=1;k<=m;k++){ f>>i>>j; a[i][j]=a[j][i]=1; } f.close(); void grad() {for (int i=1;i<=m;i++) for (int j=1;j<=m;j++) if (a[i][j]) g[i]+=1; for (i=1;i<=m;i++){ cout<<"Gradul nodului "<<i<<": "<<g[i]<<" "<<endl; } } void main() { clrscr(); citire(); grad(); getch(); } f.close(); int bf_mod(int x) int c[20],p,u,i; p=u=0; c[p]=x; v[x]=1; while(p<=u) for(i=1;i<=n;i++) if (a[c[p]][i]) { if (v[i]==0) v[i]=(v[c[p]]==1)?2:1; else if (v[i]==v[c[p]]) return 0;

12.Verificare daca un graf este bipartit


#include <fstream.h> #include <conio.h> int n,a[20][20],v[20]; void citire() { fstream f("graf.in",ios::in); int m,x,y; f>>n>>m; for(int i=1;i<=m;i++) { f>>x>>y; a[x][y]=a[y][x]=1; }

u++; c[u]=i; } p++; } return 1; } int bipartit() { int x; for (x=1;x<=n;x++) if (!v[x]) if (bf_mod(x)==0) return 0; return 1; } void main() { clrscr(); citire(); if (bipartit()) cout<<"Bipartit"; else cout<<"Nu e bipartit"; getch(); }

fstream f("graf.in",ios::in); int m,x,y; f>>n>>m; for (int i=1;i<=m;i++) { f>>x>>y; a[x][y] = a[y][x] = 1; } f.close();

} void df(int x) { v[x]=1; for (int i=1;i<=n;i++) if (a[i][x] && !v[i]) df(i); } int verif() { df(1); for (int i=1;i<=n;i++) if (!v[i]) return 0; return 1; } void main() { clrscr(); citire(); if (verif()) cout<<"DA"; else cout<<"NU"; getch(); }

13.Verificare daca un graf este conex


#include <fstream.h> #include <conio.h>

int a[20][20],n,v[20]; void citire()

Comis-voiajorul - Grafuri hamiltoniene


/* Un comis voiajor trebuie s prezinte n N orase produsele firmei sale, dup care s se ntoarc n orasul din care a plecat. Cunoscndu-se costul deplasrii ntre oricare dou din cele N orase, se cere s se gseasc un traseu care s viziteze o singur dat cele N orase, astfel nct costul total s fie minim. date de intrare: din fisierul trasee.txt se citesc: - pe prima linie n si m (n- numarul de orase; m- numarul de costuri) - pe urmatoarele m linii triplete de forma x y t cu semnificatia ca intre orasele x si y exista un cost t orasul de pornire se citeste de la tastatura date de iesire: pe monitor se afiseaza, orasele vizitate, in ordine, precum si costul total al deplasarii. daca nu exista nici o posibilitate de vizitare in conditiile cerute, se afiseaza un mesaj corespunzator. */ #include <fstream.h> #include <conio.h> int a[20] [20],m,n,x[20],q,nr=1,timp[100],parc[1 00][100]; int ok; void citire() {fstream f("trasee.txt",ios::in); f>>n>>m; for (int i=1;i<=m;i++) {int x,y,t; f>>x>>y>>t; a[x][y]=a[y][x] = t; } f.close(); } int calcul() {int t=0; for (int i=1;i<n;i++) t=t+a[x[i]][x[i+1]]; t=t+a[x[n]][x[q]]; return t; } void minim() {int min=timp[1],poz; for (int i=1;i<nr;i++) if (min>timp[i]){ min=timp[i]; poz=i; } cout<<"\nCostul minim este "<<min<<endl; cout<<"Drumul parcurs este: "; for (i=1;i<=n;i++) cout<<parc[poz][i]<<" "; cout<<x[q]; } void tipar() {int tp=0; for (int i=1;i<=n;i++) parc[nr][i] = x[i]; tp=calcul(); timp[nr++]=tp; ok = 1; } int solutie(int k) {return (k==n); } int valid(int k) {if (a[x[k]][x[k-1]]==0) return 0; for (int i=1;i<=k-1;i++) if (x[i]==x[k]) return 0; if (k==n && a[q][x[k]]==0) return 0; return 1; } void bkt(int k) {for (int i=1;i<=n;i++) {x[k]=i; if(valid(k)) if(solutie(k)) tipar(); else bkt(k+1); } } void main() {clrscr(); citire(); cout<<"Orasul din care porneste comis-voiajorul: "; cin>>q; x[1]=q; bkt(2); minim(); if (!ok) cout<<"Nu exista nici o posibilitate"; getch(); }

Excursie - Grafuri hamiltoniene

/* un grup de excursionisti vor sa viziteze toate cele N cabane intre care exista trasee turistice, fara a mai trece printr-o cabana pe care deja au vizitat-o. unele cabane sunt unite printr-un traseu a carui parcurgere dureaza un anumit timp. stiind ca ei se afla la o anumita cabana, x, la care vor sa si revina dupa excursie, gasiti o modalitate de a realiza aceste vizite intr-un timp total cat mai scurt. date de intrare: din fisierul trasee.txt se citesc: - pe prima linie n si m (n- numarul de cabane; m- numarul de trasee) - pe urmatoarele m linii triplete de forma x y t cu semnificatia ca intre cabanele x si y exista un traseu direct de durata t cabana de pornire se citeste de la tastatura date de iesire: pe monitor se afiseaza, cabanele vizitate, in ordine, precum si durata totala a excursiei. daca nu exista nici o posibilitate de vizitare in conditiile cerute, se afiseaza un mesaj corespunzator. */ #include <fstream.h> #include <conio.h> int a[20] [20],m,n,x[20],q,nr=1,timp[100],parc[1 00][100]; int ok; void citire() {fstream f("trasee.txt",ios::in); f>>n>>m; for (int i=1;i<=m;i++) {int x,y,t; f>>x>>y>>t; a[x][y]=a[y][x] = t; } f.close(); } int calcul() {int t=0; for (int i=1;i<n;i++) t=t+a[x[i]][x[i+1]]; t=t+a[x[n]][x[q]]; return t; } void minim() {int min=timp[1],poz; for (int i=1;i<nr;i++) if (min>timp[i]){ min=timp[i]; poz=i; } cout<<"\nTimpul minim este "<<min<<endl; cout<<"Drumul parcurs este: "; for (i=1;i<=n;i++) cout<<parc[poz][i]<<" "; cout<<x[q]; } void tipar() {int tp=0; for (int i=1;i<=n;i++) parc[nr][i] = x[i]; tp=calcul(); timp[nr++]=tp; ok = 1;

int solutie(int k) {return (k==n); } int valid(int k) {if (a[x[k]][x[k-1]]==0) return 0; for (int i=1;i<=k-1;i++) if (x[i]==x[k]) return 0; if (k==n && a[q][x[k]]==0) return 0; return 1; } void bkt(int k) {for (int i=1;i<=n;i++) {x[k]=i; if(valid(k)) if(solutie(k)) tipar(); else bkt(k+1); } } void main() {clrscr(); citire(); cout<<"Cabana de la care pornesc turistii: "; cin>>q; x[1]=q; bkt(2); minim(); if (!ok) cout<<"Nu exista nici o posibilitate"; getch();

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