Cod sursa(job #2927328)

Utilizator Andoss1710Balanica Andrei Andoss1710 Data 20 octombrie 2022 02:18:21
Problema Componente tare conexe Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.16 kb
#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";
        }

}