Sunteți pe pagina 1din 15

Ministerul Educatiei al Republicii Moldova

Universitatea de Stat din Moldova

Facultatea de
Informatica

Matematica si

Lucrarea de laborator nr 2-3


Disciplina: Algoritmica Grafurilor
Tema: Colorarea corect a grafului
Metoda Succesiv. Algoritmul lui Kruskal
Realizat : Mureanu Victor,
Studentul grupei I-21
Verificat : urcanu Calin

Chiinu 2015

Introducere
COLORAREA GRAFURILOR

Problemele de colorare ocup un loc important n teoria grafurilor att prin rezultatele
teoretice impuntoare, ct i prin utilizarea acestora la soluionarea problemelor practice. Printre
problemele practice, la soluionarea crora se folosesc rezultatele ce in de colorarea elementelor
grafului, pot fi menionate problemele ce apar n procesul de planificare a procesului de
producere, problemele de stocare i transportare a mrfurilor, problema orarului etc.
Colorarea vrfurilor

Fie

G ( X ;U )

un graf arbitrar i

numete k-colorare a vrfurilor grafului

un numr natural. Aplicaia

. Numrul

f (x)

f : X 1,2,..., k

se

asociat vrfului x se numete

culoare a acestui vrf.

Definiie . O k-colorare, determinat de aplicaia

f : X {1,2,..., k}

, se numete corect,

dac pentru oricare dou vrfuri adiacente x i y ale grafului G culorile atribuite lor sunt
distincte adic are loc relaia

f ( x) f ( y )

Graful pentru care exist o k-colorare corect se numete k-colorabil. innd cont de
definiia 1, s-ar putea de spus c o colorare corect a vrfurilor grafului G determin o partiie a
mulimii de vrfuri X n

lk

submulimi, 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 mulime stabil interior, numit clasa culorii i.

Definiie . Numrul minimal posibil de culori ntr-o colorare corect a vrfurilor grafului G
se numete numr cromatic al grafului G i se noteaz prin

n cazul
grafului

(G ) k

, se mai spune c graful

se numete minimal, dac

k (G )

(G )

este k-cromatic. O k-colorare corect a

Aplicaie. S examinm urmtoarea situaie. Presupunem c suntem o firm de lapte din


Hnceti, am achiziionat utilaje ultra-moderne din Germania i SUA i garantm cu interval de
ncredere de 95% c producem lapte fr e-uri , conservai, de calitate superioar. Vrem s ne
extindem afacerea n Chiinu. Am ncheiat relaii de parteneriat cu magazinile NR1, i suntem
gata s distribuim laptele nostru. Mai jos a fost prezentat amplasarea tuturor magazinelor

3|Page

NR1din Chiinu i distanele ntre magazine/ intersecii adiacente.

Nota* - Magazinele sunt notate cu patrate roii, iar cele mai importante intersecii cu cerc
negru/rou
Not** - Pentru simplitate, drumurile au fost alese cu dublu-sens.
Imediat, construim i graful potrivit desenului:

4|Page

k (G )
Se pune problema gsirii unei k-colorri corecte, astfel nct
, iar n cazul nostru,
(G )
= 3.
S elaborm algoritmul de colorare corect a grafului, utiliznd metoda succesiv.

1) Aranjm vrfurile grafului ntr-o ordine necresctoare a gradelor i atribuim primului vrf
din lista ordonat culoarea 1.
2) Parcurgem lista i atribuim culoarea 1 fiecrui vrf neadiacent cu nici unul din vrfurile
deja colorate cu aceast culoare. Apoi revenim la primul vrf necolorat.
3) Atribuim acestui vrf culoarea 2 i din nou parcurgem lista ordonat a gradelor vrfurilor,
colornd cu culoarea 2 fiecare vrf nc necolorat i neadiacent cu nici unul din vrfurile
deja colorate cu aceast culoare.
4) Procedeul se repet pn vor fi colorate toate vrfurile grafului.
5) Numrul de culori utilizate la aceast colorare este o aproximare a numrului cromatic al
grafului.
6) Algoritmul expus poate fi modificat. Una din modificrile simple const n reordonarea
vrfurilor necolorate dup fiecare etap de colorare. Vrfurile necolorate se rearanjeaz n
ordinea necresctoare a gradelor sale relative.
5|Page

7) Prin grade relative vom nelege gradele vrfurilor n subgraful obinut din graful iniial
dup eliminarea vrfurilor deja colorate. Dac dou vrfuri vor avea grade egale, atunci
ordinea apariiei 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

Dup cum se observ, am obinut egalitatea


corect.

k (G )

, ceea ce nseamn c colorarea a fost

Algoritmul lui Kruskal


Algoritmul lui Kruskal este un algoritm n teoria grafurilor care gsete arborele parial de
cost minim pentru un graf conex ponderat. Cu alte cuvinte, gsete submulimea muchiilor care
formeaz un arbore care include toate vrfurile i care este minimizat din punct de vedere al
costului. Dac graful nu este conex, atunci algoritmul gsete o pdure parial de cost minim
(un arbore parial de cost minim pentru fiecare component conex). Algoritmul lui Kruskal este
un exemplu de algoritm greedy.
Algoritmul funcioneaz n felul urmtor:

9|Page

Pasul 1. Construim graful T 1 =O n+ u1 , adugnd la graful vid, construit pe mulimea de


vrfuri X, muchia u1 U cu pondere minim.
Pasul 2. Pentru graful construit T i , cu i< n1 , 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
aparin nc lui T i i nu formeaz cicluri cu muchiile din T i .
Ilustrativ aceasta se observ n felul urmtor:
Pas 1) Ordonm Muchiile cresctor dup cost i alegem muchia cu cost minim. n cazul nostru
muchia EH, AB i EG au acelai cost = 3. Alegem una aleator spre exemplu EH. i atribuim
eticheta 1.

Pas 2) Alegem din AB i EG aleator. Spre exemplu AB. Verificm dac AB este adiacent cu EH
nu. Respectiv i atribuim eticheta 2.

Pas 3) Alegem EG, deoarece are costul minim. Verificm dac EG este adiacent cu arborele 1 sau
2. EG este adiacent cu EH, respectiv primete eticheta 1

10 | P a g e

Pas 3) Incrementm costul i observm c CF i CE au cost = 4. Alegem unul din ei (CF) i


verificm dac CF este adiacent cu arborele 1 sau 2 nu. i atribuim eticheta 3.

Pas 4) Verificm pe CE dac este adiacent cu arborele 1, 2 sau 3. Este adiacent cu CF , EH i EG.
Respectiv, schimbm eticheta lui CF de la 3 la 1, i continum procesul.

Pas 5) Muchia cu cost urmtor este GH = 5. Dar observm c dac o includem n arbore, ea
formeaz ciclu, deci o ignorm.
Pas 6) Cercetm CD care este adiacent cu CF, l includem n arbore 1.

Pas 7) Verificm pe BD = 7. Este adiacent cu AB i CD. Respectiv, schimbm eticheta lui AB de


la 2 la 1, adugm pe BD n arbore i continum procesul.

11 | P a g e

Pas 8) Cercetm AF = 8. Observm c dac l includem n list el formeaz ciclu. Noduri nu mai
exist, deci algoritmul finiseaz.

S interpretm algoritmul respectiv n problema noastr descris n laboratorul 2. De aceast dat


ncercm s gsim cea mai scurt distan de la noduri exreme. Cu alte cuvinte, cutm
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 lucrri de laborator am obinut urmtoarele competene:
1) Am fost familiarizat cu definiii i noiuni privind colorarea grafului i algoritmul lui
Kruskal. Ca: colorare corect, k-colorare, numr cromatic, pdure, arbore costului minim.
2) Am studiat algoritmul de gsire 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 gsirea 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 experienele pe care le-am obinut n lucrrile de laborator 2 i 3 mi va fi
folositoare n cariera mea de programator i de economist.

15 | P a g e