Documente Academic
Documente Profesional
Documente Cultură
4
Matrice de adiacenţă
Liste de adiacenţă
Listă de muchii/arce
Matrice de adiacenţă
1 2 3 4 5 6
1 0 1 1 0 1 0
2 1 0 1 1 0 1
3 1 1 0 0 0 0
4 0 1 0 0 0 1
5 1 0 0 0 0 1
6 0 1 0 1 1 0
Lista de adiacenţă
6 noduri:
2, 3, 5
1, 3, 4, 6
1, 2
2, 6
1, 6
2, 4, 5
Construcţia din lista de muchii
2 6 7 8
4
Dat un vector tata asociat unui arbore (arbore
genealogic) să se determine:
1) rădăcina arborelui
2) frunzele arborelui
3) un lanţ de la un vârf dat la rădăcină, afişat
direct şi invers = ascendenții unui vârf (afişați
de la tată în sus/ de la rădăcină în jos)
4) nivelul (generația) fiecărui vârf în arbore şi
înălţimea arborelui (=numărul de generații-1)
Rădăcina este vârful care are tata egal cu 0
int radacina(){ function radacina:integer;
int i; var i:integer;
for(i=1;i<=n;i++) begin
if(tata[i]==0) for i:=1 to n do
return i; if tata[i]=0 then
return 0; radacina:=i;
} end;
Frunzele sunt vârfurile care nu apar în
vectorul tata
Varianta 1 – Testăm pentru fiecare vârf
i=1… n dacă apare în vectorul tata
Complexitate?
void frunze1(){ procedure frunze1;
int i,j,ok; var i,j:integer;
for(i=1;i<=n;i++){ ok:boolean;
ok=1; begin
for(j=1;j<=n;j++) for i:=1 to n do
if (i==tata[j]) begin
ok=0; ok:=true;
if (ok) for j:=1 to n do
cout<<i<<' '; if i=tata[j] then
} ok:=false;
cout<<endl; if ok then
} write(i,' ');
end;
writeln;
end;
Varianta 1 – Complexitate: O(n2)
Varianta 2 – cu vector de apariții
Complexitate: O(n)
void frunze(){ procedure frunze;
int i; var i:integer;
int v[100]; v:array[1..100] of boolean;
begin
for(i=1;i<=n;i++) for i:=1 to n do
v[i]=0; v[i]:=true;
Idee:
- Marcăm x și ascendenții lui x
- Urcăm din y spre rădăcină până la primul vârf
marcat
Parcurgere = o modalitate prin care, plecând
de la un vârf de start și mergând pe
arce/muchii să ajungem la toate vârfurile
accesibile din s
Un vârf v este accesibil din s dacă există un
drum/lanț de la s la v în G.
Idee: Dacă
u este accesibil din s
uvE(G)
atunci v este accesibil din s.
(“din aproape în aproape”)
Parcurgerea în lățime (BF = breadth first)
1 9
8
3 2
6
7
4 1
5
1 9
8
3 2
135926478
7
4 1
5
1 9
8
3 2
135926478
7
4 1
5
1 9 3 5 9
8
3 2
135926478
7
4 1
5
1 9 3 5 9
8
3 2
135926478
7
4 1
5
1 9 3 5 9
8
3 2
1 3 5 9 6 42 7 8
7
4 1
5
1 9 3 5 9
8
3 2 2 6
1 35926478
7
4 1
5
1 9 3 5 9
8
3 2 2 6
135926478
7
4 1
5
1 9 3 5 9
8
3 2 2 6
13 5926478
7
4 1
5
1 9 3 5 9
8
3 2 2 6
135926478
7
4 1
5
1 9 3 5 9
8
3 2 2 6
135 926478
7
4 1
5
1 9 3 5 9
8
3 2 2 6 4 7 8
135 926478
7
4 1
5
1 9 3 5 9
8
3 2 2 6 4 7 8
135926478
7
4 1
5
1 9 3 5 9
8
3 2 2 6 4 7 8
1359 26478
7
4 1
5
1 9 3 5 9
8
3 2 2 6 4 7 8
135926478
7
4 1
5
1 9 3 5 9
8
3 2 2 6 4 7 8
13592 6478
7
4 1
5
1 9 3 5 9
8
3 2 2 6 4 7 8
135926478
7
4 1
5
1 9 3 5 9
8
3 2 2 6 4 7 8
135926 478
7
4 1
5
1 9 3 5 9
8
3 2 2 6 4 7 8
135926478
7
4 1
5
1 9 3 5 9
8
3 2 2 6 4 7 8
1359264 78
7
4 1
5
1 9 3 5 9
8
3 2 2 6 4 7 8
135926478
7
4 1
5
1 9 3 5 9
8
3 2 2 6 4 7 8
13592647 8
7
4 1
5
1 9 3 5 9
8
3 2 2 6 4 7 8
135926478
Vârfurile vizitate trebuie marcate:
1 9 3 5 9
8
3 2 2 6 4 7 8
6
for(i=1;i<=n;i++) {
viz[i]=0;
Inițializări tata[i]=0;
d[i]=32000;
pentru i=1,n executa }
viz[i]0
tata[i]0
niv[i]
procedure BF(s) void bf(int s){
coada C ; int p,u,i,j;
adauga(s, C) p = u = 1; c[1]=s;
viz[s] 1 viz[s]=1;
cat timp C executa while(p<=u){
i extrage(C); i=c[p]; p=p+1;
afiseaza(i); cout<<i<<" ";
for(j=1;j<=n;j++)
pentru j vecin al lui i
if(a[i][j]==1)
daca viz[j]=0 atunci if(viz[j]==0){
adauga(j, C) u=u+1; c[u]=j;
viz[j] 1 viz[j]=1;
tata[j] i tata[j]=i;
d[j] d[i]+1 d[j]=d[i]+1;
}
}
}
procedure BF(s) void bf(int s){
coada C ; int p,u,i,j;
adauga(s, C) p = u = 1; c[1]=s;
viz[s] 1; niv[s] 0 viz[s]=1;
cat timp C executa while(p<=u){
i extrage(C); i=c[p]; p=p+1;
afiseaza(i); cout<<i<<" ";
for(j=1;j<=n;j++)
pentru j vecin al lui i
if(a[i][j]==1)
daca viz[j]=0 atunci if(viz[j]==0){
adauga(j, C) u=u+1; c[u]=j;
viz[j] 1 viz[j]=1;
tata[j] i tata[j]=i;
d[j] d[i]+1 d[j]=d[i]+1;
}
}
}
procedure BF(s) void bf(int s){
coada C ; int p,u,i,j;
adauga(s, C) p = u = 1; c[1]=s;
viz[s] 1; niv[s] 0 viz[s]=1;
cat timp C executa while(p<=u){
i extrage(C); i=c[p]; p=p+1;
afiseaza(i); cout<<i<<" ";
for(j=1;j<=n;j++)
pentru j vecin al lui i
if(a[i][j]==1)
daca viz[j]=0 atunci if(viz[j]==0){
adauga(j, C) u=u+1; c[u]=j;
viz[j] 1 viz[j]=1;
tata[j] i tata[j]=i;
d[j] d[i]+1 d[j]=d[i]+1;
}
}
}
procedure BF(s) void bf(int s){
coada C ; int p,u,i,j;
adauga(s, C) p = u = 1; c[1]=s;
viz[s] 1; niv[s] 0 viz[s]=1;
cat timp C executa while(p<=u){
i extrage(C); i=c[p]; p=p+1;
afiseaza(i); cout<<i<<" ";
for(j=1;j<=n;j++)
pentru j vecin al lui i
if(a[i][j]==1)
daca viz[j]=0 atunci if(viz[j]==0){
adauga(j, C) u=u+1; c[u]=j;
viz[j] 1 viz[j]=1;
tata[j] i tata[j]=i;
d[j] d[i]+1 d[j]=d[i]+1;
}
}
}
procedure BF(s) void bf(int s){
coada C ; int p,u,i,j;
adauga(s, C) p = u = 1; c[1]=s;
viz[s] 1; niv[s] 0 viz[s]=1;
cat timp C executa while(p<=u){
i extrage(C); i=c[p]; p=p+1;
afiseaza(i); cout<<i<<" ";
for(j=1;j<=n;j++)
pentru j vecin al lui i
if(a[i][j]==1)
daca viz[j]=0 atunci if(viz[j]==0){
adauga(j, C) u=u+1; c[u]=j;
viz[j] 1 viz[j]=1;
tata[j] i tata[j]=i;
d[j] d[i]+1 d[j]=d[i]+1;
}
}
}
procedure BF(s) void bf(int s){
coada C ; int p,u,i,j;
adauga(s, C) p = u = 1; c[1]=s;
viz[s] 1; niv[s] 0 viz[s]=1;
cat timp C executa while(p<=u){
i extrage(C); i=c[p]; p=p+1;
afiseaza(i); cout<<i<<" ";
for(j=1;j<=n;j++)
pentru j vecin al lui i
if(a[i][j]==1)
daca viz[j]=0 atunci if(viz[j]==0){
adauga(j, C) u=u+1; c[u]=j;
viz[j] 1 viz[j]=1;
tata[j] i tata[j]=i;
d[j] d[i]+1 d[j]=d[i]+1;
}
}
}
procedure BF(s) void bf(int s){
coada C ; int p,u,i,j;
adauga(s, C) p = u = 1; c[1]=s;
viz[s] 1; niv[s] 0 viz[s]=1;
cat timp C executa while(p<=u){
i extrage(C); i=c[p]; p=p+1;
afiseaza(i); cout<<i<<" ";
for(j=1;j<=n;j++)
pentru j vecin al lui i
if(a[i][j]==1)
daca viz[j]=0 atunci if(viz[j]==0){
adauga(j, C) u=u+1; c[u]=j;
viz[j] 1 viz[j]=1;
tata[j] i tata[j]=i;
niv[j] niv[i]+1 d[j]=d[i]+1;
}
}
}
int n;
int a[20][20];
int viz[20],tata[20],niv[20];
Inițializări int p,u,c[20];
ok=1;
for(i=1;i<=n;i++)
if(viz[i]==0)
ok=0;
Graful este conex dacă, prin apelul parcurgerii din
vârful 1, sunt vizitate toate vârfurile
Graful este conex dacă, prin apelul parcurgerii din
vârful 1, sunt vizitate toate vârfurile
bf(1);
ok=1;
for(i=1;i<=n;i++)
if(viz[i]==0)
ok=0;
if(ok==1)
cout<<“conex”;
else
cout<<“neconex”;
Într-un grup de n persoane se cunosc
perechile de persoane care pot comunica
direct.
int main(){
int c[100],p,u;
f>>n>>r;
//construim matricea de adiacenta coresp. regulilor
for(i=1;i<=r;i++){
f>>x>>y;
a[x][y]=1;
gin[y]++;
}
//adaugam toate elementele cu grad intern 0 in coada c
p=0;u=-1;
for(i=1;i<=n;i++)
if(gin[i]==0)
{
u++; c[u]=i;
}
/*extragem un element de grad 0 din coada,
il adaugam in solutie si il eliminam din graf = scadem
cu 1 gradul intern al vecinilor sai;
Daca se obtin astfel varfuri de grad intern 0, le
adaugam in coada c */
while(p<=u){
x=c[p]; p++;
g<<x<<" ";
for(j=1;j<=n;j++)
if(a[x][j]==1){
gin[j]--;
if(gin[j]==0){
u++;
c[u]=j;
}
}
}
Temă
1. Modificați programul astfel încât graful să fie
memorat cu liste de adiacență
2. Modificați programul astfel încât să fie
detectată existența de circuite (date incorecte –
dependențe circulare)
Varianta 2 – folosim parcurgerea în adâncime DF
o Cu cât un vârf este finalizat (explorat cu toate
vârfurile accesibile din el) mai târziu în
parcurgerea DF, cu atât el este mai la început în
ordonare (în sortarea topologică)
o Adăugăm într-o stivă vârfurile, pe măsura terminării
explorării lor (adică explorării tuturor vecinilor)
for(i=1;i<=n;i++)
if(viz[i]==0){
bf(i);
cout<<i<<‘ ‘;
}
Idee – modelăm problema cu un graf
◦ Traseul mesajului în fiecare componentă = lista de fii
pentru arborele bf memorat în vectorul tata (câte un
arbore pentru fiecare componentă)
1 9
8
3 2
6
7 1
4
5
1 9
8
3 2
6
7 1
4
5
3
1 9
8
3 2
6
7 1
4
5
3
1 9
8
2
3 2
6
7 1
4
5
3
1 9
8
2
3 2
6 9
7 1
4
5
3
1 9
8
2
3 2
6 9
4
7 1
4
5
3
1 9
8
2
3 2
6 9
8
7 1
4
5
3
1 9
8
2
3 2
6 9
8
7 1
4
5
3
1 9
8
2
3 2
6 9
8
7 1
4
5
3
1 9
8
2
3 2
6 9
4 7
8
7 1
4
5
3
1 9
8
2
3 2
6 9
4 7
8
7 1
4
5
3
1 9
8
2
3 2
6 9
4 7
8
7 1
4
5
3
1 9
8
2
3 2
6 9
4 7
8
7 1
4
5
3
1 9
8
2 6
3 2
6 9
4 7
8
7 1
4
5
3
1 9
8
2 6
3 2
6 9
4 7
8
7 1
4
5
3
1 9
8
2 6
3 2
6 9
4 7
8
7 1
4
5
3 5
1 9
8
2 6
3 2
6 9
4 7
8
7 1
4
5
3 5
1 9
8
2 6
3 2
6 9
4 7
8
7 1
4
5
3 5
1 9
8
2 6
3 2
6 9
4 7
8
void df(int i){
viz[i]=1;
cout<<i<<" ";
for(int j=1;j<=n ;j++)
if(a[i][j]==1)
if(viz[j]==0){
tata[j]=i;
df(j);
}
}
Apel:
df(s)
void df(int i){
viz[i]=1;
cout<<i<<" ";
for(int j=1;j<=n ;j++)
if(a[i][j]==1)
if(viz[j]==0){
tata[j]=i;
df(j);
}
}
Apel:
df(s)
void df(int i){
viz[i]=1;
cout<<i<<" ";
for(int j=1;j<=n ;j++)
if(a[i][j]==1)
if(viz[j]==0){
tata[j]=i;
df(j);
}
}
Apel:
df(s)
void df(int i){
viz[i]=1;
cout<<i<<" ";
for(int j=1;j<=n ;j++)
if(a[i][j]==1)
if(viz[j]==0){
tata[j]=i;
df(j);
}
}
Apel:
df(s)
void df(int i){
viz[i]=1;
cout<<i<<" ";
for(int j=1;j<=n ;j++)
if(a[i][j]==1)
if(viz[j]==0){
tata[j]=i;
df(j);
}
}
Apel:
df(s)
Dat un graf neorientat, să se verifice dacă
graful conține cicluri și, în caz afirmativ,
să se afișeze un ciclu al său