Sunteți pe pagina 1din 14

GRAFURI NEORIENTATE 

Un  graf  este  o  pereche  ordonata  G=(V,M),  unde  V  este  multimea  nodurilor,  iar  M  este  multimea 
muchiilor, muchii alcatuite din elemene ale multimii V.  

Un exemplu de graf ar fi drumurile dintr‐un oras in care intersectiile reprezinta nodurile, iar drumurile 
reprezinta muchiile. 

Pentru a reprezenta informatic grafic avem doua solutii: matricea de adiacenta(costisitoare ca spatiu 
de memorie) si listele de adiacenta sau de vecini(reprezentarea se poate face folosind liste alocate 
dinamic sau tipul vector din biblioteca vector). 

Matricea de adiacenta pentru graful anterior este: 

  1  2  3  4  5  6  7  8  9 
1  0  0  0  1  1  0  0  0  0 
2  0  0  0  1  0  1  0  0  0 
3  0  0  0  0  0  0  0  0  1 
4  1  1  0  0  0  0  1  0  0 
5  1  0  0  0  0  0  1  0  0 
6  0  1  0  0  0  0  1  0  0 
7  0  0  0  1  1  1  0  0  0 
8  0  0  0  0  0  0  0  0  1 
9  0  0  1  0  0  0  0  1  0 
 

Se observa da daca exista muchie intre nodul i si nodul j a[i][j]=1, altfel a[i][j]=0. 

Matricea de adiacenta va avea zero pe diagonala principala si 1 in rest, iar numarul de valori de 1 va 
reprezenta 2*numarul de muchii al grafului. 

O alta metoda de reprezentare este lista de vecini sau de adiacenta: 

1: 4, 5 

2: 4, 6 

3: 9 
4: 1, 2, 7 

5: 1, 7 

6: 2, 7 

7: 4, 5, 6 

8: 9 

9: 3, 8 

Numarul de muchii care trec printr‐un nod se numeste grad. Deci, gradul unui nod va fi dat de numarul 
sau  de  vecini  sau  de  suma  valorilor  de  pe  linia(sau  coloana)  corespunzatoare  din  matricea  de 
adiacenta. 

Astfel 4 are gradul 3 si 8 are gradul 1 

Un nod care are graul 1 se numeste nod terminal, iar un nod care are gradul 0 nod izolat. 

Suma gradelor tuturor varfurilor este egala cu dublul numarului de muchii. 

In  general,  un  graf  neorientat  este  reprezentat  complet  dandu‐se  numarul  de  noduri,  numarul  de 
muchii si apoi muchiile. Graful se citeste dintr‐un fisier text sau de la tastatura si este transformat intr‐
o matrice de adiacenta. Atunci cand se citesc muchiile se poate calcula si memora gradul fiecarui nod 
intr‐un vector. 

De exemplu, graful anterior se poate introduce astfel(in graf.txt): 

9 9 

1 4 

1 5 

2 4 

2 6 

3 9 

4 7 

5 7 

6 7 

8 9 

Mai jos am citit graful anterior, l‐am transformat in matrice de adiacenta si am calculat gradul fiecarui 
nod. De asemenea am scris o functie care calculeaza gradul unui nod x folosind matricea de adiacenta. 
In plus am afisat lista de vecini a unui nod x si apoi listele de vecini ale grafului. 

Listing graf.cpp 
#include <iostream> 
#include<fstream> 
using namespace std; 
 
int grad[100] = { 0 };//declar vectorul gradelor 
 
void ReadGraph(int& n, int a[100][100]) 

  int i, j, x, y, m; 
  ifstream fin("graf.txt"); 
  fin >> n >> m; 
  //initializez matricea de adiacenta 
  for (i = 1; i <= n; i++) 
    for (j = 1; j <= n; j++) 
      a[i][j] = 0; 
  for (i = 1; i <= m; i++) 
  { 
    fin >> x >> y;//citesc muchia 
    a[x][y] = a[y][x] = 1; 
    grad[x]++;//calculez gradul 
    grad[y]++;//calculez gradul 
  } 
  fin.close(); 

 
int DegreeOfX(int n, int a[100][100], int x) 

  int i, grad = 0; 
  for (i = 1; i <= n; i++) 
    grad += grad + a[x][i]; 
  return grad; 

 
void NeighboorOfX(int n, int a[100][100], int x) 

  int i; 
  for (i = 1; i <= n; i++) 
    if (a[x][i] == 1) 
      cout << i << " "; 
  cout << endl; 

 
void Neighboors(int n, int a[100][100]) 

  int i; 
  for (i = 1; i <= n; i++) 
  { 
    cout << i << ": "; 
    NeighboorOfX(n, a, i); 
  } 

 
void WriteGraph(int n, int a[100][100]) 

  int i, j; 
  for (i = 1; i <= n; i++) 
  { 
    for (j = 1; j <= n; j++) 
      cout << a[i][j] << " "; 
    cout << endl; 
  }   

 
void Degrees(int n, int v[]) 

  int i; 
  for (i = 1; i <= n; i++) 
    cout << "Gradul lui " << i << " este " << grad[i] << endl; 

 
int main() 

  int n, a[100][100]; 
  ReadGraph(n, a); 
  WriteGraph(n, a); 
  Degrees(n, grad); 
  Neighboors(n, a); 

Tipuri particulare de grafuri: 

Graf regulat: graf in care toate nodurile au acelasi grad. 

Graf complet: graf in care intre orice 2 noduri exista o muchie care le leaga (gradul unui nod este n‐1, 
suma gradelor este n*(n‐1), iar numarul de muchii este n*(n‐1)/2). 

Un subgraf se obtine din graful initial prin eliminarea unuia sau mai multe noduri si a muchiilor care 
trec prin acestea. 

Un graf partial se obtine din graful initial prin eliminarea uneia sau multor muchii. 

Observatie. Graful initial va reprezenta un caz particular de subgraf sau graf partial(atunci cand nu 
elimin nici un nod sau nicio muhie). 

Numarul total de grafuri neorientate cu n noduri este 2n*(n‐1)/2. Cum se obtine aceasta valoare? 

Graful  orientat  cu  n  noduri  si  cele  mai  multe  muchii  este  cel  complet,  care  are  n*(n‐1)/2  muchii. 
Celelalte grafuri cu n noduri sunt grafuri partiale ale acestui graf obtinute prin eliminarea a cate unei 
muchii, 2 muchii, …, n muchii. Astfel, numarul de grafuri cu n noduri se calculeaza astfel(stiind ca cel 
mai mare numar de muchii posibil este n*(n‐1)/2): 
∗ ∗
𝐶 ∗ 𝐶 ∗ 𝐶 ∗ 𝐶 ∗ 2  

Mai sus, prima valoare reprezinta graful complet cu n noduri, iar ultima valoare graful cu n noduri si 
nicio muchie. 

Tot la fel se poate deduce ca numarul de subgrafuri cu x noduri ale unui graf initial cu n noduri este 
𝐶 , iar numarul total de subgrafuri este 2n(valoarea se deduce ca mai sus). 

Tot la fel se poate deduca ca numarul de grafuri partiale cu x muchii ale unui graf initial cu m muchii 
este 𝐶 , iar numarul total de subgrafuri este 2m(valoarea se deduce ca mai sus). 

In general, pentru a crea un subgraf prin program se va adauga pe rand cate un nod si se va verifica 
proprietatea ceruta de problema, iar pentru a crea un graf partial se va adauga pe rand cate o muchie 
si se va verifica proprietatea ceruta de problema. 

Un lant este o insiruire de noduri, astfel incat, intre orice doua noduri vecine din insiruire sa existe o 
muchie care sa le lege. 

Exemplu: 1 5 7 5 este un lant 

1 5 7 5 2 nu este lant 

Un lant elementar este un lant in care nu se repeta nodurile. 
1 5 7 6 este un lant elementar 

Un lant simplu este un lant in care nu repeta muchiile 

1 5 7 6 este si un lant simplu 

Presupun ca in vectorul chain am retinut o insiruire de x noduri. Functiile de mai jos verifica daca chain 
este lant, daca este lant elementar si daca este lant simplu: 
int Chain(int a[100][100], int x, int chain[]) 

  int i; 
  if (x == 1) return 0; 
  for (i = 1; i <= x ‐ 1; i++) 
    if (a[chain[i]][chain[i + 1]] == 0) return 0; 
  return 1; 

 
int ElementaryChain(int a[100][100], int x, int chain[]) 

  int i, j; 
  if (Chain(a, x, chain) == 0) return 0; 
  for (i = 1; i <= x ‐ 1; i++) 
    for (j = i + 1; j <= x; j++) 
      if (chain[i] == chain[j]) return 0; 
  return 1; 

 
int SimpleChain(int a[100][100], int x, int chain[]) 

  int B[100][100] = { 0 }, i, j; 
  //B este o matrice a lantului in care pun fiecare muchie care se repeta in lant 
  //Daca o muchie se repeta returnez 0 
  if (Chain(a, x, chain) == 0) return 0; 
  for (i = 1; i <= x ‐ 1; i++) 
    if (B[chain[i]][chain[i + 1]] == 1) return 0; 
    else B[chain[i]][chain[i + 1]] = B[chain[i + 1]][chain[i]] = 1; 
  return 1; 

Un ciclu este un lant simplu care are cel putin patru noduri si in care primul si ultimul nod trebuie sa 
fie identice. 
int Cycle(int a[100][100], int x, int chain[]) 

  if (x <= 3) return 0; 
  if (chain[1] != chain[x])return 0; 
  if (SimpleChain(a, x, chain) == 0) return 0; 
  return 1; 

Un  algoritm  foarte  simplu  si  usor  de  implementat,  dar  care  consuma  timp  este  algoritmul  care 
genereaza matricea lanturilor(algoritmul Floyd‐Warshall). Algoritmul se bazeaza pe urmatoarea idee 
se ia fiecare nod k de la 1 la n si se procedeaza astfel: daca nu exista lant intre i si j se verifica daca 
exista lant intre i si k si intre k si j. Daca exista acest lant i k j atunci va exista lant intre i si j. 
 void FloydWarshall(int a[100][100], int n) 

  int i, j, k; 
  for (k = 1; k <= n; k++) 
    for (i = 1; i <= n; i++) 
      for (j = 1; j <= n; j++) 
        if (i != j and j != k and k != i and a[i][k] == 1 and 
a[k][j] == 1) a[i][j] = 1; 

Odata cu matricea lanturilor apare si notiunea de conexitate. 

Un graf este conex daca intre orice doua noduri ale sale exista un lant care le leaga. 

Un graf poate avea una(si atunci este graf conex) sau mai multe componente conexe. 

O componenta conexa a unui graf este un subgraf conex al acestuia in care proprietatea de conexitate 
este maximala(adica nu mai exista alte noduri ale grafului initial care sa poata face parte din aceasta 
componenta). Un nod izolat(de grad 0) este o componenta conexa. 

In graful de mai sus exista doua componente conexe: 1, 2, 4, 5, 6, 7 si 3, 8, 9. 

1, 2,  4,  5, 6 nu este componenta conexa, deoarece mai exista nodul 7 care  poate  apartine acestei 


componente. 

Folosind matricea lanturilor pot verifica daca un graf este conex sau pot afisa lantul care leaga doua 
noduri sau chiar componentele conexe ale unui graf. 

O  modalitate  eficienta  de  a  rezolva  acest  tip  de  probleme  este  de  a  utiliza  cele  doua  parcurgeri: 
parcurgerea in latime(Breath First) si parcurgerea in adancime(Depth First). 

Parcurgerea in latime 

Pentru parcurgerea in latime vom folosi doi vectori: q(care va functiona ca o coada – adica elementele 
vor fi adaugate la sfarsitul vectorului, iar vectorul va fi parcurs de la inceput) si viz care va marca cu 1 
fiecare element vizitat. 

Cum se face parcurgerea? La fiecare pas se stabileste nodul curent din coada si se afiseaza vecinii lui 
nevizitati. 

Daca  nodul  din  care  fac  parcurgerea  va  fi  2  parcurgerea  si  vectorii  vor  arata  astfel(pe  rand  se  vor 
adauga vecinii lui 2 – 4 si 6, ai lui 4 – 1 si 7, ai lui 1 – 5): 

  1  2  3  4  5  6  7  8  9
q  2                 
viz  0  1  0  0  0  0  0  0  0
    1  2  3  4  5  6  7  8  9
q  2  4  6             
viz  0  1  0  1  0  1  0  0  0
  1  2  3  4  5  6  7  8  9
q  2  4  6  1  7         
viz  1  1  0  1  0  1  1  0  0
Pentru 6 nu adaug nimic pentru ca 
vecinii lui 6 au fost deja marcati(2 si 
7). Voi adauga pentru 1 doar pe 5 
  1  2  3  4  5  6  7  8  9
q  2  4  6  1  7  5       
viz  1  1  0  1  1  1  1  0  0
Pentru 5 si 7 nu mai am pe cine sa adaug asa ca ma opresc din parcurgere. Se poate vedea ca am 
parcurs doar prima componenta conexa. 
void BreathFirst(int n, int a[100][100], int x) 

  int first, last, i, q[100], viz[100] = { 0 }; 
  first = last = 1; 
  q[last] = x; 
  viz[x] = 1; 
  while (first <= last) 
  { 
    int current_node = q[first]; 
    cout << current_node << " "; 
    for(i = 1; i <= n; i++) 
      if (a[current_node][i] == 1 and viz[i] == 0) 
      { 
        //cout << i; 
        q[++last] = i; 
        viz[i] = 1; 
      } 
    first++; 
  } 

In cazul in care vreau sa verific daca graful este conex fac parcurgerea din orice nod si returnez variabila 
last. Daca last este egal cu n graful este conex. 

Parcurgerea imi va afisa elementele componentei conexe din care face parte x.  

Parcurgerea in latime imi poate afisa, deci, componetele conexe ale unui graf si numraul lor astfel: 
void BreathFirst(int n, int a[100][100], int x, int viz[]) 

  int first, last, i, q[100]; 
  first = last = 1; 
  q[last] = x; 
  viz[x] = 1; 
  while (first <= last) 
  { 
    int current_node = q[first]; 
    cout << current_node << " "; 
    for (i = 1; i <= n; i++) 
      if (a[current_node][i] == 1 and viz[i] == 0) 
      { 
        //cout << i; 
        q[++last] = i; 
        viz[i] = 1; 
      } 
    first++; 
  } 

In main: 
for(i=1;i<=n;i++) 
    if (viz[i] == 0) 
    { 
      cc++; 
      cout << "Componenta conexa " << cc << ": "; 
      BreathFirst(n, a, i, viz); 
      cout << endl; 
    } 
  cout << cc << endl; 

De asemenea, se mai pot adauga doi vectori pred si lg. Lg poate calcula lungimea celui mai scurt lant 
dintre nodul x si oricare alt nod din graf, iar cu ajutorul lui pred s poate afisa chiar lantul. pred[i] va fi 
egal cu nodul din care provine i in timpul parcurgerii in latime: 

  1  2  3  4  5  6  7  8  9
q  2               
viz  0  1  0  0  0  0  0  0  0
pred  0               
    1  2  3  4  5  6  7  8  9
q  2  4  6           
viz  0  1  0  1  0  1  0  0  0
pred    0    2    2     
  1  2  3  4  5  6  7  8  9
q  2  4  6  1  7       
viz  1  1  0  1  0  1  1  0  0
pred  4  0    2    2  4   
Pentru  6  nu  adaug  nimic  pentru  ca 
vecinii  lui  6  au  fost  deja  marcati(2  si 
7). Voi adauga pentru 1 doar pe 5 
  1  2  3  4  5  6  7  8  9
q  2  4  6  1  7  5       
viz  1  1  0  1  1  1  1  0  0
pred  4  0    2  1  2  4     
 

Cum se afiseaza lantul dintre 2 si 7? 

Mai intai se afiseaza 7, apoi pred[7], adica 4. Apoi pred[4] adica 2, apoi pred[2] adica ma opresc. 

Deci 7 4 2, care este cel mai scurt lant posibil. Pentru a afisa in ordinea 2 4 7 voi folosi recursivitatea. 
void BreathFirst(int n, int a[100][100], int x, int lg[], int pred[]) 

  int first, last, i, q[100], viz[100] = { 0 }; 
  first = last = 1; 
  q[last] = x; 
  viz[x] = 1; 
  lg[x] = 0; 
  pred[x] = 0; 
  while (first <= last) 
  { 
    int current_node = q[first]; 
    cout << current_node << " "; 
    for (i = 1; i <= n; i++) 
      if (a[current_node][i] == 1 and viz[i] == 0) 
      { 
        q[++last] = i; 
        viz[i] = 1; 
        lg[i] = lg[current_node] + 1; 
        pred[i] = current_node; 
      } 
    first++; 
  } 

void lant(int x, int pred[]) 

  if (x != 0) 
  {   
    lant(pred[x], pred); 
    cout << x << " "; 
     
  } 

In main: 
x = 2; 
  BreathFirst(n, a, x, lg, pred); 
  for (i = 1; i <= n; i++) 
  { 
    cout << "Lungimea lantului dintre " << x << " si " << i << " este " << 
lg[i]<<" iar lantul este: "; 
    lant(i, pred); 
    cout << endl; 
 
  } 

Parcurgerea in adancime 

Parcurgerea in adancime foloseste o stiva si un vector viz pentru parcurgere, astfel incat, in momentul 
in care elementul din varful stivei nu mai are vecini este sters si se trece la urmatorul element. Se 
procedeaza astfel: se afiseaza elementul, se marcheaza, se afiseaza primul lui vecin, se marcheaza etc. 
Daca nodul curent nu mai are vecini se coboara un nivel in stiva si se afiseaza primul vecin nevizitat al 
acestuia. Pentru a simula stiva cel mai simplu este sa se foloseasca recursivitatea: 

  1  2  3  4  5  6  7  8  9
stack  2                 
viz  0  1  0  0  0  0  0  0  0
    1  2  3  4  5  6  7  8  9
stack  2  4               
viz  0  1  0  1  0  0  0  0  0
  1  2  3  4  5  6  7  8  9
stack  2  4  1             
viz  1  1  0  1  0  0  0  0  0
  1  2  3  4  5  6  7  8  9
stack  2  4  1  5           
viz  1  1  0  1  1  0  0  0  0
  1  2  3  4  5  6  7  8  9
stack  2  4  1  5  7         
viz  1  1  0  1  1  0  1  0  0
  1  2  3  4  5  6  7  8  9
stack  2  4  1  5  7  6       
viz  1  1  0  1  1  1  1  0  0
 

Elementul din varful stivei este 6 care nu are vecini nevizitati, apoi 7, la fel etc pana cand stiva devine 
goala. Daca folosim recursivitatea nu mai e nevoie sa folosesc stiva. 

Vectorul viz se declara global si se initializeaza cu 0. 
void DepthFirst(int n, int a[100][100], int x) 

  int i; 
  cout << x << " "; 
  viz[x] = 1; 
  for (i = 1; i <= n; i++) 
    if (a[i][x] == 1 and viz[i] == 0) 
      DepthFirst(n, a, i); 

Tema. Sa se afiseze componentele conexe si lungimea acestora folosind parcurgerea in adancime. 

Sa se verifice daca un graf este aciclic sau nu. Se va adapta functia de parcurgere in adancime. 

Functia de mai jos verifica daca un nod face parte dintr‐un ciclu sau nu. 
int HasCycle(int n, int a[100][100], int x, int pred) 

  int i; 
  viz[x] = 1;//marchez x ca vizitat 
  for (i = 1; i <= n; i++) 
    if (a[x][i] == 1)//daca i este vecin al lui x 
      if(viz[i] == 0)//daca nu a fost marcat 
        if (HasCycle(n, a, i, x) == 0) return 0;//daca el este 
parte dintr‐un ciclu 
        else;//daca nu este parte a unui ciclu nu fac nimic 
      else if (pred != i) return 0;//daca i este marcat si nu este 
predecesorul lui x returnez 0 
  return 1;//daca scap nu am cicluri 

Un graf bipartit este un graf in care nodurile sale pot fi impartite in doua multimi A si B, astfel incat 
intre nodurile care apartin unei multimi sa nu existe muchie. 

Tema. Sa se adapteze DFS astfel incat sa se verifice daca un graf este bipartit sau nu. 

Un graf este graf eulerian daca contine un ciclu eulerian. Un ciclu este eulerian daca contine toate 
muchiile grafului. Un graf eulerian are gradele tuturor nodurilor pare. 

Un  graf  este  hamiltonian  daca  contine  un  ciclu  hamiltonian.  Un  ciclu  este  hamiltonian  daca  este 
elementar si contine toate nodurile grafului. 

Urmatoarea functie va afisa un ciclu eulerian. Mai intai se va verifica daca graful are toate gradele 
pare, apoi se va adapta DFS astfel: pentru fiecare vecin al unui nod x, acesta va fi eliminat din graf. 
Fiecare nod x va fi adaugat la o coada, care va fi fisata la final. 
void EulerCycle(int n, int a[100][100], int x) 

  int i; 
  for(i=1;i<=n;i++) 
    if (a[x][i] == 1) 
    { 
      a[x][i] = a[i][x] = 0; 
      EulerCycle(n, a, i); 
    } 
  q[++el] = x; 

In main: 
for (i = 1; i <= n and Euler == 1; i++) 
    if (grad[i] % 2 == 1) Euler = 0; 
  if (Euler == 1) EulerCycle(n, a, 1); 
  for (i = 1; i <= el; i++) cout << q[i] << " ";  

 
GRAFURI ORIENTATE 
Un  graf  orientat  este  o  pereche  ordonata  G=(V,M)  unde  V={x/x  este  multimea  varfurilor},  iar 
M={(x,y)/x,y apartin lui V}. Daca exista (x,y) nu este obligatorie relatia inversa. 

Reteaua de drumuri dintr‐un oras este un graf orientat(vezi sensurile unice). 

Un graf orientat poate fi reprezentat prin matrice de adiacenta sau liste de vecini: 

  1  2  3  4  5  6 
1  0  0  1  0  0  0 
2  1  0  0  0  0  0 
3  1  1  0  0  0  0 
4  1  0  0  0  1  0 
5  0  0  0  0  0  1 
6  0  0  0  1  0  0 
 

Matricea nu este simetrica fata de diagonala principala. Numarul de valori de 1 din matrice este egal 
cu numarul de muchii. 

Reprezentarea prin liste de vecini este urmatoarea: 

1: 3 

2: 1 

3: 1, 2 

4: 1, 5 

5: 6 

6: 4 

Un nod are grad interior si grad exterior. Gradul interior este dat de numarul de arce care intra intr‐
un varf, iar gradul exterior de numarul de arce care ies dintr‐un varf. 

Suma valorilor de pe linia x a matricei este gradul exterior al lui x, iar suma valorilor de pe coloana x a 
matricei este gradul interior. 
Varf  Grad exterior  Grad interior
1  1  3 
2  1  1 
3  2  1 
4  2  1 
5  1  1 
6  1  1 
 

Se observa ca suma gradelor interioare ale grafului este egala cu suma gradelor interioare si este egala 
cu numarul de arce. 

In general, un graf orientat este reprezentat complet dandu‐se numarul de varfuri, numarul de arce si 
apoi arcele. Graful se citeste dintr‐un fisier text sau de la tastatura si este transformat intr‐o matrice 
de adiacenta. Atunci cand se citesc arcele se poate calcula si memora gradul interior sau exterior al 
fiecarui varf in doi vector. 

De exemplu, graful anterior se poate introduce astfel(in graf.txt): 

6 8 

1 3 

2 1 

3 1 

3 2 

4 1 

4 5 

5 6 

6 4 

Mai jos am citit graful anterior, l‐am transformat in matrice de adiacenta si am calculat gradele fiecarui 
varf. De asemenea am scris o functie care calculeaza gradul exterior unui varf x folosind matricea de 
adiacenta si una care calculeaza gradul interior al unui varf folosind matricea de adiacenta. In plus am 
afisat lista de vecini a unui varf x si apoi listele de vecini ale grafului. 

Listing graf.cpp 
#include <iostream> 
#include<fstream> 
using namespace std; 
 
int gradext[100] = { 0 }, gradint[100] = { 0 };//declar vectorul gradelor 
 
void ReadGraph(int& n, int a[100][100]) 

  int i, j, x, y, m; 
  ifstream fin("graf.txt"); 
  fin >> n >> m; 
  //initializez matricea de adiacenta 
  for (i = 1; i <= n; i++) 
    for (j = 1; j <= n; j++) 
      a[i][j] = 0; 
  for (i = 1; i <= m; i++) 
  { 
    fin >> x >> y;//citesc muchia 
    a[x][y] = 1; 
    gradext[x]++;//calculez gradul exterior 
    gradint[y]++;//calculez gradul interior 
  } 
  fin.close(); 

 
int ExtDegreeOfX(int n, int a[100][100], int x) 

  int i, grad = 0; 
  for (i = 1; i <= n; i++) 
    grad += grad + a[x][i]; 
  return grad; 

 
int IntDegreeOfX(int n, int a[100][100], int x) 

  int i, grad = 0; 
  for (i = 1; i <= n; i++) 
    grad += grad + a[i][x]; 
  return grad; 

 
 
void NeighboorOfX(int n, int a[100][100], int x) 

  int i; 
  for (i = 1; i <= n; i++) 
    if (a[x][i] == 1) 
      cout << i << " "; 
  cout << endl; 

 
void Neighboors(int n, int a[100][100]) 

  int i; 
  for (i = 1; i <= n; i++) 
  { 
    cout << i << ": "; 
    NeighboorOfX(n, a, i); 
  } 

 
void WriteGraph(int n, int a[100][100]) 

  int i, j; 
  for (i = 1; i <= n; i++) 
  { 
    for (j = 1; j <= n; j++) 
      cout << a[i][j] << " "; 
    cout << endl; 
  }   

 
void Degrees(int n, int v[]) 

  int i; 
  for (i = 1; i <= n; i++) 
    cout << "Gradul exterior al lui " << i << " este " << gradext[i] << 
endl; 
for (i = 1; i <= n; i++) 
    cout << "Gradul interior al lui " << i << " este " << gradint[i] << 
endl; 

 
int main() 

  int n, a[100][100]; 
  ReadGraph(n, a); 
  WriteGraph(n, a); 
  Degrees(n, grad); 
  Neighboors(n, a); 

Numarul total de grafuri neorientate cu n noduri este 4n*(n‐1)/2. 

Numarul  de  subgrafuri  cu  x  varfuri  ale  unui  graf  initial  cu  n  noduri  este  𝐶 ,  iar  numarul  total  de 
subgrafuri este 2n(valoarea se deduce ca mai sus). 

Numarul de grafuri partiale cu x muchii ale unui graf initial cu m muchii este 𝐶 , iar numarul total de 
subgrafuri este 2m(valoarea se deduce ca mai sus). 

Un drum este o insiruire de varfuri, astfel incat, intre orice doua noduri vecine din insiruire sa existe 
un arc care sa le lege. 

Un drum elementar este un drum in care nu se repeta nodurile. 

Un drum simplu este un drum in care nu repeta arcele. 

Un ciclu este un drum simplu care are cel putin patru varfuri si in care primul si ultimul varf trebuie sa 
fie identice. 

Un graf orientat este tare conex daca oricare ar fi doua varfuri x si y din graf va exista drum si intre x 
si y si intre y si x. 

O componenta tare conexa este un subgraf al grafului initial care este tare conex si in care proprietatea 
de tare conexitate este maximala. Graful de mai sus are doua componente tare conexe: 

1 2 3 

4 5 6 

Pentru  a  verifica  ca  un  graf  este  tare  conex  se  va  folosi  matricea  drumurilor,  matrice  care  se 
construieste cu algoritmul Floyd‐Warshall. 

De asemenea, se pot construi componentele tare conexe folosind matricea drumurilor, parcurgerea 
in latime sau parcurgerea in adancime. 

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