Pagini recente » Cod sursa (job #467996) | Cod sursa (job #2166554) | Cod sursa (job #2954986) | Cod sursa (job #955688) | Cod sursa (job #2927328)
#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
using namespace std;
//pentru acesta problema, vom folosii algoritmul lui Tarjans pentru
//componente tari conexe
int ord = 0;//pentru a numerota in ordine nodurile pe care le parcurgem in graf
stack<int> stiva;//bagam valorile pe care le parcurgem in dfs pentru a stii unde am fost
//deja pe timpul acelei parcurgeri dfs
int instack[100001];//array ce retine daca un element este in stack sau nu
int low_link[100001];//retine nodul cel mai mic din ordine la care poate ajunge nodul curent
int ids[100001];//numeroteaza numerele in ordine
int cnt;//retine nr de componente conexe
vector<vector<int>> lista_ctc(100001);//lista ce retine liste cu nodurile componentelor conexe
void dfs(int n, vector<vector<int>> &lista){
ord++;
//bagam noul nod in stack
stiva.push(n);
instack[n] = 1;//bifam ca este in stack
ids[n] = ord;//ii atribuim ordinea
low_link[n] = ord;//si nodul cel mai mic in care se duce(la momentul actual fiind chiar el)
for(int i = 0; i<lista[n].size(); i++){//verificam vecinii nodului
if(ids[lista[n][i]]==0) dfs(lista[n][i], lista);//daca nu e vizitat, atunci facem dfs
//si pt el
//dupa ce n-am intors din dfs-ul vecinului sau daca am verificat ca vecinul a fost deja vizitat
//ne intrebam daca vecinul este deja in stack
//daca este, inseamna ne-am intors la un nod la care deja fusesem in aceasta verificare dfs
//deci putem spune ca low_link ar fi minimul dintre low_linkul lui si cel al nodului vecin
//deoarece oriunde ar merge vecinu, merge si cel curent pentru ca are o muchie la vecin
//daca nu e in stack, inseamna ca face deja parte din alta componenta tare conexa
if(instack[lista[n][i]]==1)
low_link[n] = min(low_link[n], low_link[lista[n][i]]);
}
//daca ne-am intors pana la nodul care are acelasi id si low_link, inseamna ca am in stack
//toate elementele unui ctc
if(ids[n]==low_link[n]){
while(stiva.top()!=n){
//puncem fiecare element din stack pana la nodul curent intr-un vector pt a retine ctc-ul
lista_ctc[cnt].push_back(stiva.top());
instack[stiva.top()] = 0;//dez-verificam nodul
stiva.pop();//si in scoatem din stack
}
//facem si pt nodul n
lista_ctc[cnt].push_back(stiva.top());
instack[stiva.top()] = 0;
stiva.pop();
cnt++;//am completatun ctc, deci crestem nr de ctc-uri
}
}
int main()
{
ifstream fin("ctc.in");
ofstream fout("ctc.out");
int n, m;
fin>>n>>m;
vector<vector<int>> lista(n+1);//lista de adiacenta
for(int i = 0; i<m; i++){
int x, y;
fin>>x>>y;
lista[x].push_back(y);
}
for(int i = 1; i <=n; i++){//verificam fiecare element sa fie verificat
//si daca nu, facem dfs
if(ids[i]==0){
dfs(i, lista);
}
}
fout<<cnt<<"\n";
for(int i = 0; i<cnt; i++){
for(int j = 0; j<lista_ctc[i].size(); j++)
fout<<lista_ctc[i][j]<<" ";
fout<<"\n";
}
}