Sunteți pe pagina 1din 9

Ministerul Educaţiei al Republicii Moldova

Universitatea Tehnică a Moldovei


Catedra ATI

RAPORT
Lucrare de laborator nr.2
la Matematica Discreta
Tema: Algoritmul de căutare în adîncime.

A elaborat:
st. gr. AI-171 Crușnevschi Stanislav

A verificat: Tiholaz Tatiana

Chișinău 2018
1. SCOPUL LUCRĂRII:
 Studierea algoritmului de determinare a grafului de acoperire şi elaborarea programelor
care vor realiza acest algoritm.
2. NOTE DE CURS
Noţiune de graf de acoperire
Fie H un subgraf care conţine toate vârfurile unui graf arbitrar G. Dacă pentru fiecare
componentă de conexitate a lui G subgraful H va defini un arbore atunci H se va numi graf de
acoperire (scheletul sau carcasă) grafului G. Este evident că graful de acoperire există pentru
oricare graf: eliminând ciclurile din fiecare componentă de conexitate, adică eliminând muchiile
care sunt în plus, vom ajunge la graful de acoperire.
Se numeşte graf aciclic orice graf care nu conţine cicluri. Pentru un graf arbitrar G cu n vârfuri şi
m muchii sunt echivalente următoarele afirmaţii:
1. G este arbore;
2. G este un graf conex şi m = n - 1;
3. G este un graf aciclic şi m = n - 1;
4. oricare două vârfuri distincte (diferite) ale lui G sunt unite printr-un lanţ simplu care este
unic;
5. G este un graf aciclic cu proprietatea că, dacă o pereche oarecare de vârfuri neadiacente vor
fi unite cu o muchie, atunci graful obţinut va conţine exact un ciclu.
Consecinţă: numărul de muchii pentru un graf arbitrar G, care va fi necesar a fi eliminate spre a
obţine un graf de acoperire nu depinde de ordinea eliminării lor şi este egal cu
m(G)-n(G)+k(G),
unde m(G), n(G) şi k(G) sunt numărul de muchii, vârfuri şi componente conexe, respectiv.
Numărul s(G) = m(G)-n(G)+ k(G) se numeşte rang ciclic sau număr ciclomatic al grafului G.
Numărul r(G) = n(G)-k(G) – rang cociclomatic sau număr cociclomatic.
Deci, s(G)+r(G)=m(G).
Este adevărată următoarea afirmaţie: orice subgraf a unui graf arbitrar G se conţine într-un graf
de acoperire a grafului G.
Algoritmul de determinare a grafului de acoperire
Există mai mulţi algoritmi de determinare a grafului de acoperire. Algoritmul de mai jos nu este
un algoritm-standard, ci este unul elaborat în bază algoritmului de căutare în lărgime. Esenţa
algoritmului constă în aceea că folosind două fire de aşteptare în unul din care sunt înscrise (pe
rând) numerele vârfurilor adiacente cu vârfurile din celălalt FA (ca şi în cazul căutării în
lărgime), vor fi eliminate muchiile dintre vârfurile unui FA şi toate muchiile în afară de una
dintre fiecare vârf al FA curent şi vârfurile din FA precedent. în cazul În care ambele FA vor
deveni vide procedura se va termina.
Pentru a nu admite ciclarea şi ca să fim siguri că au fost prelucrate toate componentele conexe se
va utiliza marcarea vârfurilor. Dacă după terminarea unui ciclu ordinar nu au mai rămas vârfuri
nemarcate procedura ia sfârşit, în caz contrar în calitate de vârf iniţial se va lua oricare din
vârfurile nemarcate.
3. SARCINA DE BAZĂ
1. Elaboraţi organigrama algoritmului şi programul procedurii de determinare a grafului de
acoperire cu posibilităţi de pornire a procedurii din oricare vârf al grafului.
2. Utilizând procedurile de introducere a grafului în memoria CE din lucrarea Nr. 1, elaboraţi
un program cu următoarele facilităţi:
 introducerea grafului care este dat sub formă de matrice de incidenţă, adiacenţă sau listă
de adiacenţă;
 determinarea grafului de acoperire, pornind de la un vârf arbitrar;
 extragerea informaţiei la display sau imprimantă în oricare din formele numite.

Codul în limbajul de programare C


#include<stdio.h>
#include<conio.h>
#define MAX_ARCURI 50
#define MAX_VARFURI 20
struct Elem {
int N;
struct Elem *P;
};
typedef Elem* ElemPtr;
typedef int MAdiacenta[MAX_VARFURI] [MAX_VARFURI];
typedef int MIncidenta[MAX_ARCURI] [MAX_VARFURI];
int cd[MAX_VARFURI];
int i;
int all; // variabila va contine numarul de noduri din graf
ElemPtr Pt; // pointer, va fi folosit pentru a accesa elementele listei de adiacenta
MAdiacenta MA;
MIncidenta MI;
ElemPtr T[MAX_VARFURI]; // declararea listei de adiacenta
//initializarea listei de adiacenta
void InitListAdiacenta(void)
//functia data este folosita pentru initializarea listei
{
int i;
for (i=0; i<MAX_VARFURI; i++)
while (T[i]->N !=0)
{
Pt=T[i];
T[i]=Pt->P;
delete Pt;
}}
// Introducerea Listei de adiacenta
void InLA(void)
{
int i, top;
printf("Introducerea listei de adiacenta :\n");
printf("Numarul de varfuri :");
scanf("%d",&all); // all = numarul de varfuri
for (i=0; i<all; i++)
{
T[i] = new Elem;
// alocarea in memoriei pentru un nou element at listei
Pt=T[i];
Pt->N =0; // setarea valorii nodului ca 0
printf("varful %d :",i+1);
while (1) // ciclu infinit pana la un break
{
scanf("%d",&top);
// citirea cate un element pana la intalnirea 0;
if (top != 0)
{
Pt->N = top; // adaugarea elementului la lista
Pt->P = new Elem; // alocarea memoriei pentru un nou element
Pt = Pt->P; //avansarea in lista
Pt->N =0; // setarea valorii ca 0
}
else break; // in caz cand intalnim 0 introducerea valorilor pentru
// varful curent is sfarsit
}
printf("\n");
}
printf("\n");
}
// Introducerea Matricei de adiacenta
void InMA(void)
{
int i, il;
printf(" Introducerea Matricei de Adiacenta \n");
printf(" Numarul de varfuri : ");
scanf("%d",&all); // numarul de varfuri
for(i=0; i<all; i++)
for(il=0; il<all; il++)
{
MA[i][il]=0; // curatarea matricei
if (i != il) // nu certam pentru bucle
{
printf("\n Din varful %d in %d :", i+1,il+1);
scanf("%d",&MA[i][il]); //citirea valorii a(i,j)
}}

InitListAdiacenta(); //curatarea listei

for (i=0; i<all; i++)


{
Pt=T[i]; //pregatirea pentru a misca prin lista
for(il=0 ;il<all; il++)
{
if (MA[i][il]!=0)
{
Pt->N=il+1; // setarea valorii nodului current
Pt->P = new Elem;
// alocarea memorie pentru un nou element at listei
Pt=Pt->P; // avansarea
Pt->N=0; //settarea sfarsitului
} }}}

// introducerea matricei de incidenta


void InMI(void)
{
int AllLink;
int i,il; // variabile contor
int Sr,Tg;
printf("Introducerea matricei de incidenta \n");
printf("Numarul de arcuri : ");
scanf("%d",&AllLink); // citirea numarului de arcuri
printf("\nNumarul de varfuri : ");
scanf("%d",&all); //citirea numarului de varfuri
for(i=0;i<all;i++)
for (il=0; il<AllLink; il++)
{
printf("\nVarful %d si arcul %d ", i+1, il+1);
scanf("%d",&MI[i][il]); //citirea elementului dat
}

InitListAdiacenta();
for (i=0; i<AllLink; i++)
{
Sr=0; Tg=0;
for (il=0;il<all; il++)
{
if(MI[il][i]==1) Tg=il; //nodul - il este destinatia arcului
if (MI[il][i]==-1) Sr=il; //nodul - il este sursa arcului
}
if (Sr != 0)
{
Pt=T[Sr]; //adaugam nodul pentru elementul sursa
while (Pt->N != 0)
{
if (Pt->N==Tg) goto label1;
Pt= Pt->P;
}
Pt->N=Tg; //adaugarea nodului
Pt->P = new Elem; //alocarea memoriei
Pt->P->N=0; //setarea sfarsitului listei de noduri
label1 :
;
} }}
char t[MAX_VARFURI];
void initT(void)
{
for (int i=0; i<MAX_VARFURI; i++) t[i]=0;
}
MAdiacenta a;
void createMA()
{
int i,il;
for(i=0; i<MAX_VARFURI; i++) //curatarea matricei
for(il=0; il<MAX_VARFURI; il++) a[i][il]=0;
for(i=0; i<all; i++) //pentru toate varfurile
{
Pt=T[i]; //setam pointerul de parcurgere
while (Pt->N != 0) //pana nu s-a ajuns la sfarsit
{
if (a[i][Pt->N-1]==0) a[i][Pt->N-1]=1;
//crearea matricei
Pt=Pt->P; //avansarea in lista
}}}
MAdiacenta b;
void parcinadinc(int k) // parcurgerea in adancime
{
int i;
t[k]=1;
for (i=0; i<all; i++)
if ((a[k][i]==1) && (t[i]==0))
{
b[k][i]=1;
parcinadinc(i);
}}
void grafacoperire()
{
int i,j;
for(i=0; i<all; i++)
for(j=0; j<all; j++) b[i][j]=0;
createMA();
initT();
parcinadinc(0);
printf("\n Graful de acoperire \n");
for (i=0; i<all; i++)
{ printf("%3d:",i+1 );
for (j=0; j<all; j++)
if(b[i][j]!=0){
printf("%d",j+1);}
printf("\n");
}}
int main(void) //programul principal
{
unsigned int ch; //variabile pentru meniu
for (int i=0; i<MAX_VARFURI; i++)
{
T[i]=new Elem;
T[i]->N=0;
}
do
{
printf(" ---Introduceti graful sub urmatoarele forme:1,2,3--- \n");
printf("1. Lista de Adiacenta\n");
printf("2. Matricea de Adiacenta\n");
printf("3. Graf de acoperire \n");
printf("4. Iesire\n");
ch=getch();
switch (ch) {
case '1' :InLA();break; //introducerea listei de adiacenta
case '2' :InMA();break; //introducerea matricei de adiacenta
case '5' :InMI();break; //introducerea matricei de incidenta
case '3' :grafacoperire();break; //graf de acoperire
}}
while (ch != '4'); //repeta pana s-a ales Iesire
}
Rezultatul

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