Documente Academic
Documente Profesional
Documente Cultură
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.
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.
Doua componente conexe C1 si C2 sunt doua multimi disjuncte sau doua multimi
egale intre ele.
Fiecare nod apartine exact unei singure componente conexe
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
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.
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