Se dă un digraf (graf orientat) cu n
noduri numerotate de la 1
la n
. Graful componentelor tare conexe se obține astfel: se construiesc componentele tare conexe, apoi fiecare astfel de componentă devine nod în noul graf. Apoi din lista inițială de arce se păstrează în noul graf numai arcele care au extremitățile în componente tare conexe diferite. Dacă există mai multe arce între aceleași două noduri în noul digraf, se păstrează toate.
Componentele tare conexe se vor construi astfel: prima componentă este cea care conține nodul 1
, a doua componentă este cea care conține cel mai mic nod care nu se află în prima componentă ș.a.m.d.
Lista de adiacență asociată unui nod i
din digraful componentelor tare conexe conține toate nodurile j
cu proprietatea că există arcul (i, j)
.
Cerința
Să se afișeze listele de adiacență asociate noului digraf.
Date de intrare
Programul citește de la tastatură numerele n
și m
, iar apoi m
perechi de forma i j
cu semnificația: există arcul (i,j)
în digraf.
Date de ieșire
Programul va afișa pe ecran nrC
linii, unde nrC
este numărul componentelor tari conexe, adică numărul de noduri din noul graf. Pe fiecare din următoarele i
linii se vor afișa, în ordine crescătoare adiacenții externi ai nodului i
din noul digraf. Dacă există k
arce (i, j)
atunci în lista de adiacență a lui i
nodul j
va apărea de k
ori, deci se va afișa de k
ori. Dacă un nod k
din noul digraf are gradul exterior 0
, se va afișa doar un 0
.
Restricții și precizări
1 ≤ n ≤ 100.000
1 ≤ m ≤ 200.000
- în toate testele, digraful are cel puțin două componente tari conexe
Exemplu
Intrare
8 10 1 2 2 3 3 1 4 5 5 6 6 7 7 4 6 4 4 1 4 8
Ieșire
0 1 3 0
Explicație
Graful are 8
noduri și 10
arce:
Prima componentă conexă este formată cu nodurile 1 2 3
, a doua cu nodurile 4 5 6 7
, iar a treia este formată din nodul 8
. Din digraful inițial se păstrează numai arcele (4,1)
și (4,8)
. Graful asociat componentelor tare conexe este:
#include <bits/stdc++.h> using namespace std; stack <int> S; int n , m , x , y , v[100001] , L[100001] , cnt , inS[100001] , rez , e , s[100001] , viz[100001] , T[100001]; vector <int> G[100001]; vector <int> P[100001]; vector <int>c; vector <vector<int>> cc; void tarjan(int nod) { cnt++; v[nod] = L[nod] = cnt; S.push(nod); inS[nod] = 1; for(auto i:G[nod]) { if(!v[i]) tarjan(i) , L[nod] = min(L[nod] , L[i]); else if(inS[i] == 1) L[nod] = min(L[nod] , v[i]); } if(v[nod] == L[nod]) { c.clear(); while(1) { int val = S.top(); S.pop(); c.push_back(val); inS[val] = 0; if(nod == val) break; } rez++; for(auto i:c) s[i] = rez; } } int main() { cin >> n >> m; for(int i = 1 ; i <= m ; i++) { cin >> x >> y; G[x].push_back(y); } for(int i = 1 ; i <= n ; i++) if(!v[i]) cnt = 0 , tarjan(i); int c = 1; for(int i = 1 ; i <= n ; i++) if(!T[s[i]]) T[s[i]] = c++; for(int i = 1 ; i <= n ; i++) s[i] = T[s[i]]; /*for(int i = 1 ; i <= n ; i++) cout << s[i] << " "; cout << '\n';*/ for(int i = 1 ; i <= n ; i++) for(auto j : G[i]) if(s[i] != s[j]) P[s[i]].push_back(s[j]) , viz[s[i]] = viz[s[j]] = 1; for(int i = 1 ; i <= rez; i++) { sort(P[i].begin() , P[i].end()); } for(int i = 1 ; i <= rez ; i++) { int ok = 0; for(auto j:P[i]) ok++; if(viz[i] != 0 && ok == 0) cout << 0 << '\n'; if(ok != 0) { for(auto j : P[i]) cout << j << " "; cout << '\n'; } } }