Sunteți pe pagina 1din 7

Componente tare conexe – Algoritmul lui

Kosaraju in C++
By Matraguna Mihai Last updated feb. 7, 2019

 0

 Share

Astazi vom vorbii despre componentele tare (sau tari?) conexe ale unui graf orientat,
rezolvand problema ctc – infoarena.ro.

Ce este o componenta tare conexa?


In Teoria Grafurilor, o componenta este tare conexa daca poti ajunge dintr-un nod in
oricare alt nod. Insa aceste componente tare conexe pot forma mai multe sub-partitii
care sunt conectate intre ele. (vezi exemplul de mai jos)

In acest graf orientat avem 3 componente tare conexe.

 Componenta 1: 1, 2, 3
 Componenta 2: 4, 5
 Componenta 3: 6, 7, 8

Putem observa cum cele 3 componente conexe sunt la randul lor, accesibile intre ele.

Definitie: G1 = (V1, E1) este o componenta tare conexa daca:

 pentru orice pereche x, y de varfuri din V1 exista un drum de la x la y si drum de


la y la x
 nu exista alt subgraf al lui G, G2=(V2, E2) care sa indeplineasca prima conditie
si care sa-l contina pe G1
Proprietatile unei componente conexe:

 Doua componente conexe C1 si C2 sunt doua multimi disjuncte sau doua multimi
egale intre ele.
 Fiecare nod apartine exact unei singure componente conexe

Problema CTC – infoarena.ro


Pentru a intelege mai bine componentele conexe vom rezolva problema ctc de pe
infoarena.ro: click.

Enunt: Dandu-se un graf orientat G = (V, E) se cere sa se determine componentele


sale tare conexe.

Avem mai sus


exemplul din problema, desenat si observam ca sunt doua componente conexe in total.
Pentru a rezolva acest tip de problema exista doi algoritmi: algoritmul lui Kosaraju si
algoritmul lui Tarjan.

Algoritmul lui Kosoraju


Algoritmul lui Kosoraju este urmatorul:

 Pasul 1: Creeaza o stiva goala „S” si parcurge graful printr-un DFS. In momentul
cand te intorci din parcurgerea recursiva („zona 4” din DFS – vorbim despre asta
mai jos) – pune nodul in stiva. De exemplu, in problema de mai sus obtinem

stiva: 7 4 8 5 6 3 2 1 (unde 1 este ultimul element introdus in stiva).


 Pasul 2: Inversam directiile grafului pentru a construi transpusa acestuia.

Inversa
grafului din problema

 Pasul 3: Scoate cate un element rand pe rand din stiva „S”. Daca elementul
selectat nu a mai fost vizitat, porneste o parcurgere DFS in graful construit la
pasul 2. De fiecare data cand vom porni un DFS vom avea o noua componenta
conexa.

Algoritmul lui Kosoraju – Cum functioneaza?


In exemplul de pe Wikipedia se explica cel mai bine cum sta treaba.

Avem in figura de mai sus


un graf format din punctuletele mici albastre. Daca condensam graful (ne uitam la
punctele galbene) – observam faptul ca acesta devine un graf orientat aciclic. Acelasi
lucru se intampla si in exemplul problemei noastre, obtinem graful acilic:
(patratul albastru reprezinta un nod iar patratul mov reprezinta alt nod)

Teorema: Pentru orice graf orientat G, in momentul cand il condensam, obtinem un


graf aciclic ( demonstratia – aici. )

Asadar, ajungem la urmatoarea observatie: componentele tare conexe dintr-un graf


formeaza intre ele un graf orientat aciclic. Daca abstractizam putin teorema, putem sa
gandim graful pe doua nivele. Primul nivel este reprezentat de componentele tare
conexe din graful aciclic (nodurile galbene / dreptunghiurile), iar cel de-al doilea nivel
este reprezentat de nodurile ce formeaza fiecare componenta conexa.

O operatie utila atunci cand vine vorba de grafuri orientate aciclice este sortarea
topologica. Deoarece aceasta ne garanteaza ca daca exista un arc (i, j), atunci i apare
inaintea lui j in aceasta sortare.

Sortand topologic graful de mai sus, obtinem stiva de elemente scrisa sub acesta.
Putem observa faptul ca pornind pe rand cate un DFS din fiecare nod, putem
determina componentele conexe ale acestuia.
 

Avem aici
graful din problema. De-asupra fiecarui nod se gaseste timpul in care s-a pornit un DFS
din acesta (numarul albastru) si timpul in care s-a incheiat un DFS din acesta (numarul
visiniu). Asadar, sortand timpii de finish, obtinem stiva formata din nodurile 7 4 8 5 6 3
2 1.

Daca parcurgem transpusa grafului printr-un DFS (pornind din nodul 1), observam
faptul ca acesta determina cate o componenta conexa. (inversand sensul grafului ti se
garanteaza faptul ca o parcurgere DFS determina componenta conexa).

Algoritmul in C++
Algoritmul lui Kosoraju - Componente tare conexe
C++

1 #include    <fstream>
2 #include    <iostream>
3 #include    <vector>
4 #include    <stack>
5  
6 #define NMax 100005
7  
8 using namespace std;
9  
10 ifstream fin("ctc.in");
11 ofstream fout("ctc.out");
12  
13 stack < int > S;
14  
15 vector<int> G[NMax],GT[NMax],CTC[NMax];
16  
17 int N, M, NrCTC;
18 int beenThere[NMax];
19  
20 void Read()
21 {
22     fin >> N >> M;
23     for(int i = 1; i <= M; i++)
24     {
25         int x,y;
26         fin >> x >> y;
27         G[x].push_back(y); // Construim graful G
28         GT[y].push_back(x); // Construim transpusa grafului G
29     }
30 }
31  
32 void DFSP(int Nod)
33 {
34     beenThere[Nod] = 1;
35     for(unsigned int i=0; i<G[Nod].size();i++) {
36         int Vecin = G[Nod][i];
37  
38         if(!beenThere[Vecin])
39             DFSP(Vecin);
40     }
41     S.push(Nod);
42 }
43  
44 void DFSM(int Nod)
45 {
46     beenThere[Nod] = 2;
47     CTC[NrCTC].push_back(Nod);
48  
49     for(unsigned int i=0; i<GT[Nod].size();i++) {
50         int Vecin = GT[Nod][i];
51  
52         if(beenThere[Vecin]==1)
53             DFSM(Vecin);
54     }
55 }
56  
57 void Solve()
58 {
59     for(int i=1;i<=N;i++)
60         if(!beenThere[i])
61             DFSP(i);
62  
63     while(!S.empty()) {
64         int Nod = S.top();
65         cout << Nod << " ";
66         if (beenThere[Nod] == 1) {
67             NrCTC++;
68             DFSM(Nod);
69         }
70         S.pop();
71     }
72 }
73  
74 void Print()
75 {
76     fout << NrCTC <<"\n";
77  
78     for(int i = 1; i <= NrCTC; i++) {
79         for(unsigned int j = 0; j < CTC[i].size(); j++)
80             fout << CTC[i][j] <<" ";
81         fout<<"\n";
82     }
83 }
84  
85 int main()
86 {
87     Read();
88     Solve();
89     Print();
90     return 0;
91 }

 
algoritmul lui kosarajuc++componenta tare conexacomponente tare conexectckosarajuteoria grafurilor

 0

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