Sunteți pe pagina 1din 15

Ministerul Educatiei al Republicii Moldova

Universitatea de Stat din Moldova

„Facultatea de Matematica si
Informatica”

Lucrarea de laborator nr 2-3

Disciplina: “Algoritmica Grafurilor”


Tema: ” Colorarea corectă a grafului ”
Metoda Succesivă. Algoritmul lui Kruskal
Realizat : Mureșanu Victor,
Studentul grupei I-21

Verificat : Țurcanu Calin

Chișinău 2015
Introducere

COLORAREA GRAFURILOR

Problemele de colorare ocupă un loc important în teoria grafurilor atât prin rezultatele
teoretice impunătoare, cât şi prin utilizarea acestora la soluţionarea problemelor practice. Printre
problemele practice, la soluţionarea cărora se folosesc rezultatele ce ţin de colorarea elementelor
grafului, pot fi menţionate problemele ce apar în procesul de planificare a procesului de
producere, problemele de stocare şi transportare a mărfurilor, problema orarului etc.

Colorarea vârfurilor

G  ( X ;U ) k f : X  1,2,..., k 
Fie un graf arbitrar şi un număr natural. Aplicaţia se

G f (x)
numeşte k-colorare a vârfurilor grafului . Numărul asociat vârfului x se numeşte
culoare a acestui vârf.

f : X  {1,2,..., k}
Definiţie . O k-colorare, determinată de aplicaţia , se numeşte corectă,
dacă pentru oricare două vârfuri adiacente x şi y ale grafului G culorile atribuite lor sunt

f ( x)  f ( y )
distincte adică are loc relaţia .

Graful pentru care există o k-colorare corectă se numeşte k-colorabil. Ţinând cont de
definiţia 1, s-ar putea de spus că o colorare corectă a vârfurilor grafului G determină o partiţie a

lk
mulţimii de vârfuri X în submulţimi, adică

X  X 1 U X 2 U ... X l l  k
, ,

2|Page
X i ∩ X j=Ø .

Fiecare clasă X i=1,2, … , l este o mulţime stabilă interior, numită clasa culorii i.

Definiţie . Numărul minimal posibil de culori într-o colorare corectă a vîrfurilor grafului G

 (G )
se numeşte număr cromatic al grafului G şi se notează prin .

 (G )  k G
În cazul , se mai spune că graful este k-cromatic. O k-colorare corectă a

G k   (G )
grafului se numeşte minimală, dacă .

Aplicație. Să examinăm următoarea situație. Presupunem că suntem o firmă de lapte din


Hâncești, am achiziționat utilaje ultra-moderne din Germania și SUA și garantăm cu interval de
încredere de 95% că producem lapte fără e-uri , conservați, de calitate superioară. Vrem să ne
extindem afacerea în Chișinău. Am încheiat relații de parteneriat cu magazinile NR1, și suntem
gata să distribuim laptele nostru. Mai jos a fost prezentată amplasarea tuturor magazinelor

3|Page
NR1din Chișinău și distanțele între magazine/ intersecții adiacente.

Nota* - Magazinele sunt notate cu patrate roșii, iar cele mai importante intersecții cu cerc
negru/roșu
Notă** - Pentru simplitate, drumurile au fost alese cu dublu-sens.

Imediat, construim și graful potrivit desenului:

4|Page
k   (G )
Se pune problema găsirii unei k-colorări corecte, astfel încât , iar în cazul nostru,
 (G )
= 3.
Să elaborăm algoritmul de colorare corectă a grafului, utilizând metoda succesivă.

1) Aranjăm vârfurile grafului într-o ordine necrescătoare a gradelor şi atribuim primului vârf
din lista ordonată culoarea 1.
2) Parcurgem lista şi atribuim culoarea 1 fiecărui vârf neadiacent cu nici unul din vârfurile
deja colorate cu această culoare. Apoi revenim la primul vârf necolorat.
3) Atribuim acestui vârf culoarea 2 şi din nou parcurgem lista ordonată a gradelor vârfurilor,
colorând cu culoarea 2 fiecare vârf încă necolorat şi neadiacent cu nici unul din vârfurile
deja colorate cu această culoare.
4) Procedeul se repetă până vor fi colorate toate vârfurile grafului.
5) Numărul de culori utilizate la această colorare este o aproximare a numărului cromatic al
grafului.
6) Algoritmul expus poate fi modificat. Una din modificările simple constă în reordonarea
vârfurilor necolorate după fiecare etapă de colorare. Vârfurile necolorate se rearanjează în
ordinea necrescătoare a gradelor sale relative.

5|Page
7) Prin grade relative vom înţelege gradele vârfurilor în subgraful obţinut din graful iniţial
după eliminarea vârfurilor deja colorate. Dacă două vârfuri vor avea grade egale, atunci
ordinea apariţiei acestora în lista ordonată este aleatorie.

Codul C++: (Vom utiliza parcurgerea BFS)

#include <iostream>
#include <windows.h>

using namespace std;

const int MAX = 30;


int n = 19;
int rez[50],viz[50];

int culori(double[][MAX], int nr_vf);


void setcolor(int);

int main()
{
double matrix[MAX][MAX] =
{
// 1 2 3 4 5 6 7 8 9 I1 I2 I3 I4 I5 I6 I7 I8 I9 I10
{0, 1.29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //1
{1.29, 0, 2.04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.14, 0, 0, 0, 8.14}, //2
{0, 2.04, 0, 4.08, 0, 0, 0, 0, 0, 0, 0, 3.63, 0, 0, 0, 0, 0, 0, 0}, //3
{0, 0, 4.08, 0, 0.76, 0, 0, 0, 0, 0, 0, 1.77, 0, 0, 0, 0, 0, 0, 0}, //4
{0, 0, 0, 0.76, 0, 0, 0, 0, 0, 1.31, 0.8, 0, 0, 0, 0, 0, 0, 0, 0}, //5
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.6, 0, 0, 0, 0, 0, 0}, //6
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.4, 3.4, 0, 0}, //7
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.02, 0, 0.38, 0}, //8
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.38, 0, 1.56}, //9
{0, 0, 0, 0, 1.31, 0, 0, 0, 0, 0, 0.7, 0, 1.23, 0, 0, 0, 0, 0, 0}, //I1
{0, 0, 0, 0, 0.8, 0, 0, 0, 0, 0.7, 0, 0.66, 0, 1.21, 0, 0, 0, 0, 0}, //I2
{0, 0, 3.63, 1.77, 0, 0, 0, 0, 0, 0, 0.66, 0, 0, 0, 1.25, 0, 0, 0, 0}, //I3
{0, 0, 0, 0, 0, 0.6, 0, 0, 0, 1.23, 0, 0, 0, 1.46, 0, 0, 0, 0, 0}, //I4
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.21, 0, 1.46, 0, 0.54, 0.1, 0, 0, 0}, //I5
{0, 4.14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.25, 0, 0.54, 0, 0, 0, 0, 0}, //I6
{0, 0, 0, 0, 0, 0, 0.4, 3.02, 0, 0, 0, 0, 0, 0.1, 0, 0, 0, 0, 0}, //I7
{0, 0, 0, 0, 0, 0, 3.4, 0, 0.38, 0, 0, 0, 0, 0, 0, 0, 0, 0.8, 0}, //I8
{0, 0, 0, 0, 0, 0, 0, 0.38, 0, 0, 0, 0, 0, 0, 0, 0, 0.8, 0, 1.38}, //I9
{0, 8.14, 0, 0, 0, 0, 0, 0, 1.56, 0, 0, 0, 0, 0, 0, 0, 0, 1.38, 0}, //I10
};
int i, j, a, nr_vf;
int x,y,c,s,maxim=0;

6|Page
setcolor(15);

cout << "Dati nodul de inceput :";


cin >> s;
for(int i=0;i<n;i++)
if(!viz[i])
{ c=culori(matrix, s);
if(c>maxim) maxim=c;
}
cout<<"Chi = "<<maxim<<"\n";
for(int i=1;i<=maxim;i++)
{
setcolor(i+9);
cout<<"culoarea "<<i<<": ";
for(int j=0;j<n;j++)
if(viz[j]==i) cout<<j<<" ";
cout<<endl;
}

setcolor(15);
return 0;
}

void setcolor(int color){

HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE);


SetConsoleTextAttribute(hcon,color);
}

int culori(double matrix[][MAX], int nr_vf)


{
int vecin,parc,i,rez[50],j,c=1,maxim,t,gasit;
vecin=parc=0;
viz[nr_vf]=1;
rez[0] = nr_vf;
while(vecin <= parc)
{
for(i = 0; i <= n; i++)
{
if(matrix[rez[vecin]][i] && !viz[i])
{
parc++;
rez[parc] = i;
maxim = 0;
for(int k=0; k<=n; k++)
if(matrix[i][k] && viz[k] > maxim) maxim = viz[k];

7|Page
t = 1;
do {
gasit = 0;
for(int k=0; k<=n; k++)
if(matrix[i][k] && viz[k]==t) gasit=1;
if(gasit) t++;
}
while(t <= maxim && gasit);
if(gasit) viz[i] = maxim+1;
else viz[i] = t;
}
}
vecin++;
}

for(i=0;i<=parc;i++) if(viz[rez[i]]>c) c=viz[rez[i]];


return c;

Rezultat:

8|Page
k   (G )
După cum se observă, am obținut egalitatea , ceea ce înseamnă că colorarea a fost
corectă.

Algoritmul lui Kruskal

Algoritmul lui Kruskal este un algoritm în teoria grafurilor care găsește arborele parțial de
cost minim pentru un graf conex ponderat. Cu alte cuvinte, găsește submulțimea muchiilor care
formează un arbore care include toate vârfurile și care este minimizat din punct de vedere al
costului. Dacă graful nu este conex, atunci algoritmul găsește o pădure parțială de cost minim
(un arbore parțial de cost minim pentru fiecare componentă conexă). Algoritmul lui Kruskal este
un exemplu de algoritm greedy.

Algoritmul funcționează în felul următor:

9|Page
Pasul 1. Construim graful T 1 =O n+ u1 , adăugând la graful vid, construit pe mulţimea de
vârfuri X, muchia u1 ϵ U cu pondere minimă.
Pasul 2. Pentru graful construit T i , cu i< n−1 , construim graful T i +1=T i+u i+1 , unde
ui+1 este muchia grafului G=(X,U) care are ponderea minimă dintre toate muchiile, care nu

aparţin încă lui T i şi nu formează cicluri cu muchiile din T i .

Ilustrativ aceasta se observă în felul următor:

Pas 1) Ordonăm Muchiile crescător după cost și alegem muchia cu cost minim. În cazul nostru
muchia EH, AB și EG au același cost = 3. Alegem una aleator spre exemplu EH. Îi atribuim
eticheta 1.

Pas 2) Alegem din AB și EG aleator. Spre exemplu AB. Verificăm dacă AB este adiacent cu EH –
nu. Respectiv îi atribuim eticheta 2.

Pas 3) Alegem EG, deoarece are costul minim. Verificăm dacă EG este adiacent cu arborele 1 sau
2. EG este adiacent cu EH, respectiv primește eticheta 1

10 | P a g e
Pas 3) Incrementăm costul și observăm că CF și CE au cost = 4. Alegem unul din ei (CF) și
verificăm dacă CF este adiacent cu arborele 1 sau 2 – nu. Îi atribuim eticheta 3.

Pas 4) Verificăm pe CE dacă este adiacent cu arborele 1, 2 sau 3. Este adiacent cu CF , EH și EG.
Respectiv, schimbăm eticheta lui CF de la 3 la 1, și continuăm procesul.

Pas 5) Muchia cu cost următor este GH = 5. Dar observăm că dacă o includem în arbore, ea
formează ciclu, deci o ignorăm.
Pas 6) Cercetăm CD care este adiacent cu CF, îl includem în arbore 1.

Pas 7) Verificăm pe BD = 7. Este adiacent cu AB și CD. Respectiv, schimbăm eticheta lui AB de


la 2 la 1, adăugăm pe BD în arbore și continuăm procesul.

11 | P a g e
Pas 8) Cercetăm AF = 8. Observăm că dacă îl includem în listă el formează ciclu. Noduri nu mai
există, deci algoritmul finisează.

Să interpretăm algoritmul respectiv în problema noastră descrisă în laboratorul 2. De această dată


încercăm să găsim cea mai scurtă distanță de la noduri exreme. Cu alte cuvinte, căutăm
costul minim al grafului.

Codul C++:

#include <iostream>
#include<conio.h>
#include<stdlib.h>

using namespace std;


int i,j,k;
int a,b,u,v;
int n,nr=1;
double minim, costmin = 0,vizit[19];
int find(int);
int uni(int,int);

double cost[30][30] =
{
// 1 2 3 4 5 6 7 8 9 I1 I2 I3 I4 I5 I6 I7 I8 I9 I10
{0, 1.29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //1
{1.29, 0, 2.04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.14, 0, 0, 0, 8.14}, //2
{0, 2.04, 0, 4.08, 0, 0, 0, 0, 0, 0, 0, 3.63, 0, 0, 0, 0, 0, 0, 0}, //3
{0, 0, 4.08, 0, 0.76, 0, 0, 0, 0, 0, 0, 1.77, 0, 0, 0, 0, 0, 0, 0}, //4
{0, 0, 0, 0.76, 0, 0, 0, 0, 0, 1.31, 0.8, 0, 0, 0, 0, 0, 0, 0, 0}, //5
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.6, 0, 0, 0, 0, 0, 0}, //6
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.4, 3.4, 0, 0}, //7
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.02, 0, 0.38, 0}, //8
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.38, 0, 1.56}, //9
{0, 0, 0, 0, 1.31, 0, 0, 0, 0, 0, 0.7, 0, 1.23, 0, 0, 0, 0, 0, 0}, //I1
{0, 0, 0, 0, 0.8, 0, 0, 0, 0, 0.7, 0, 0.66, 0, 1.21, 0, 0, 0, 0, 0}, //I2
{0, 0, 3.63, 1.77, 0, 0, 0, 0, 0, 0, 0.66, 0, 0, 0, 1.25, 0, 0, 0, 0}, //I3

12 | P a g e
{0, 0, 0, 0, 0, 0.6, 0, 0, 0, 1.23, 0, 0, 0, 1.46, 0, 0, 0, 0, 0}, //I4
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.21, 0, 1.46, 0, 0.54, 0.1, 0, 0, 0}, //I5
{0, 4.14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.25, 0, 0.54, 0, 0, 0, 0, 0}, //I6
{0, 0, 0, 0, 0, 0, 0.4, 3.02, 0, 0, 0, 0, 0, 0.1, 0, 0, 0, 0, 0}, //I7
{0, 0, 0, 0, 0, 0, 3.4, 0, 0.38, 0, 0, 0, 0, 0, 0, 0, 0, 0.8, 0}, //I8
{0, 0, 0, 0, 0, 0, 0, 0.38, 0, 0, 0, 0, 0, 0, 0, 0, 0.8, 0, 1.38}, //I9
{0, 8.14, 0, 0, 0, 0, 0, 0, 1.56, 0, 0, 0, 0, 0, 0, 0, 0, 1.38, 0}, //I10

};
int main(void)
{

cout << "Dati numarul de noduri: ";


cin >> n;
for(i=0;i<=n;i++)
{
for(j=0;j<=n;j++)
{
if(cost[i][j] == 0)
cost[i][j]=999;
}
}
cout << "Muchiile arborelui cu cost minim sunt: " << endl;
while(nr < n) //nr- numarul muchiilor vizitate
{

for(i = 0,minim = 999;i<=n;i++)


{
for(j=1;j <= n;j++)
{
if(cost[i][j] < minim)
{
minim=cost[i][j];
a=u=i;
b=v=j;}}}
u=find(u);
v=find(v);
if(uni(u,v))
{
cout << nr++ << " muchie (" << a << ", " << b << ") =" << minim <<
endl;
costmin += minim;
}
cost[a][b]=cost[b][a]=999; // facem pe a, b verificati
}

13 | P a g e
cout << " Costul minim este :" << costmin;
return 0;
}
int find(int i)
{
while(vizit[i])
i=vizit[i];
return i;
}
int uni(int i,int j)
{
if(i!=j)
{
vizit[j]=i;
return 1;
}
return 0;
}

Rezultatul:

Graful costului minim este:

14 | P a g e
Concluzie

În urma acestei lucrări de laborator am obținut următoarele competențe:


1) Am fost familiarizat cu definiții și noțiuni privind colorarea grafului și algoritmul lui
Kruskal. Ca: colorare corectă, k-colorare, număr cromatic, pădure, arbore costului minim.
2) Am studiat algoritmul de găsire a costului minim. Algoritmul lui Kruskal.
3) Am elaborat programul în C++ de colorare a grafului prin intermediul parcurgerii BFS. Și
am elaborat programul în C++ de găsirea arborelui cu cost minim.
4) Am implementat o problemă economică reală, și am demonstrat, că defapt practic orice
problemă din lumea reală, poate fi redusă la studierea grafurilor.

Cu siguranță experiențele pe care le-am obținut în lucrările de laborator 2 și 3 îmi va fi


folositoare în cariera mea de programator și de economist.

15 | P a g e

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