---
disqus: temurbekkhujaev
---
# Kosaraju
## Kirish
Yo'nalishli $G$ graf berilgan, $V$ uchlar to'plami va $E$ qirralar to'plami.
**Kuchli bog'langan komponent** (strongly connected component) grafning shunday qismiga aytiladiki bunda har qanday $u,v \in E$ uchun $u \rightarrow v$ bajariladi, ya'ni $u$ dan $v$ ga yo'l bor.
Keyinchalik *KBK* deb qisqartirib ketamiz. Anglash mumkinki grafni KBK larga bo'lganda turli xil komponentalar bir biri bilan kesishmaydi. Grafni har bir KBK larini uchlarini bitta uchga siqib yangi graf hosil qilish **kondensatsiyalash** deyiladi. Kondetsatiya qilingan graf $G^{KBK}$ ko'rinishida yoziladi. Kondetsatsiyadan keyin graf **asiklik** ko'rinishga keladi ya'ni grafda sikllar qolmaydi. Isboti shundaki agar KBK lar sikl hosil qilsa demak shu siklni tashkil qiluvchi har bir KBK dan shu sikldagi boshqa KBK larga yo'l bor va bu o'z o'rnida kuchli bog'langan komponentalarning belgisi, demak ular alohida KBK bo'lishi mumkin emas.
**Kosaraju** algoritmi grafdagi KBK larni topishda ishlatiladi.
## Algoritm
Quyida keltirilgan algoritm realizatsiyasi $O(n+m)$ vaqt va xotira talab qiladi.
Algoritmning asosiy ideyasi shundaki kuchli bog'langan komponentalar $C_1$ va $C_2$ o'rtasida qirra bo'lishi mumkin qachonki grafdagi uchlar topologik saralanganda $C < C'$ bo'lsa. Bundan kelib chiqadiki $C_1 < C_2$ shart bajarilgan holda $C_2$dan $C_1$ga qirra mavjud bo'lsa, demak $C_1$ va $C_2$ bitta KBK da yotadi aks holda har xil.
Grafni uchlari $v \in G$ uchun topologik saralab, saralangan tartibda har bitta $v$ uchun faqat shu komponentaga kiradigan va boshqalariga kirmaydigan $u$ larni topish uchun DFS qila olsak maqsadga erishamiz.
Yuqorida ko'rsatilgandek DFS qila olish uchun biz qirralari **teskarilangan graf** $G^T$qurib shu grafda $v$ bora oladigan va hali komponentasi topilmagan $u$ larni qidirishimiz kerak.
Endi algoritmni quyidagi qadamlar orqali ko'rsatish mumkin.
1. $G$ graf uchlarini topologik saralash
2. Saralangan uchlar tartibida $G^T$ grafda *DFS* qilish va shu fazada tashrif buyurilgan uchlarni yangi komponenta sifatida belgilash
## Realizatsiya
```cpp
const int N = 1000001; #grafdagi uchlar maksimal uchlar soni
vector<int> g[N]; #original graf
vector<int> gr[N]; #teskarilangan graf
vector<int> comp_members[N]; #KBK a'zolarini saqlash uchun
vector<int> order; #topologik saralangan uchlar
int comp_index[N];
bool used[N];
void topsort(int v) {
used[v] = true;
for (auto x:g[v]) {
if (!used[x]) topsort(x);
}
order.push_back(v);
}
void dfs(int v, int current_comp) {
comp_index[v] = current_comp; # v - uchni qaysi KBK daligini belgilash
comp_members[current_comp].push_back(v); # KBK ga yangi element qo'shish
for (auto x:gr[v]) {
if (comp_index[x] == 0) { # hali KBK topilmagan bo'lsa unda DFS qilish
dfs(x, current_comp);
}
}
}
int main() {
int n, m; # grafdagi uchlar va qirralar soni
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int a, b;
cin >> a >> b;
g[a].push_back(b); #original qirralar
gr[b].push_back(a); #teskarilangan qirralar
}
for (int i = 1; i <= n; i++) { #grafni topo saralash
if (!used[i]) topsort(i);
}
int total_comps = 0; #grafda topilgan jami KBKlar
/* topsort dan keyin order teskari saralangan bo'ladi
shuning uchun butun vectorni reverse qilish kerak*/
reverse(order.begin(), order.end());
for (auto v: order) {
if (comp_index[v] == 0) {
dfs(v, ++total_comps);
}
}
for (int c = 1; c <= total_comps; c++) {
cout <<"KBK " << c << ": ";
for (auto v:comp_member[c]) { #c-komponenta a'zolarini chiqarish
cout << v << ' ';
}
cout << endl;
}
return 0;
}
```
## Qo'llanilishi
Kosaraju algoritmi 2SAT(2 satisfability) masalalarini yechishda qo'llaniladi, va ko'pincha grafdagi sikllardan halos bo'lish uchun kondensatsiya qilish ishlatiladi.
Quyidagi masalalarni Kosaraju orqali yechish mumkin:
https://codeforces.com/problemset/problem/427/C
https://codeforces.com/problemset/problem/505/D