Cod sursa(job #2930021)

Utilizator ArthurelVilceanu Razvan-Arthur Arthurel Data 27 octombrie 2022 12:41:56
Problema Componente tare conexe Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.11 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
using namespace std;

// Folosim algoritmul lui tarjan pentru a gasi componentele tare conexe
// Se parcurg nodurile prin dfs si le sunt atribuite un index si o valoare lowlink egala initial cu indexul
// Valoarea lowlink reprezinta cel mai inapoiat nod la care poate ajunge nodul respectiv
// Daca mai multe noduri au aceeasi valoare lowlink, atunci ele fac parte dintr-o componenta tare conexa
// Se pastreaza o stiva pentru a verifica daca nodurile fac parte din aceeasi parcurgere si daca le pot fi egalate valorile lowlink
// La intoarcerea din dfs calculam minimul valorilor lowlink ale unui nod cu nodul vecin daca nodul vecin este in stiva
// Golim stiva daca indexul este egal cu valoarea lowlink pentru ca inseamna ca s-a gasit inceputul componentei tare conexe

// Complexitate timp : O(N)
// Complexitate spatiu : O(N)

ifstream f("ctc.in");
ofstream g("ctc.out");

vector<vector<int>> adj_list;
vector<int> indx; //retine indexul atribuit fiecarui nod in urma parcurgerii DFS
vector<int> lowlink; // Indexul cel mai mic care poate fi accesat din nodul curent (lowlink value)

//Stiva care va verifica daca nodurile sunt in procesul de parcurgere.
// Daca un nod u intalneste un nod v care este in stiva, atunci valoarea lowlink poate fi atribuita ca minimul valorilor lowlink a celor 2 noduri
vector <bool> onStack;
stack <int> st;
int id = 0;                   // Id-ul fiecarui nod
int sccCount = 0;             //contorizeaza componentele tare conexe
vector<vector<int>> scc;    //memoreaza componentele tare conexe

//algoritmul lui tarjan
void dfs(int node){
    st.push(node);
    onStack[node] = true;
    indx[node] = lowlink[node] = ++id;

    //vizitam toti vecinii nodului si la intoarcere calculam minimul valorilor lowlink ale nodului cu nodul vecin daca nodul vecin este in stiva
    for(auto x : adj_list[node]){
        if(indx[x] == -1)
            dfs(x);
        if(onStack[x])
            lowlink[node] = min(lowlink[node], lowlink[x]);
    }
    // Golim stiva daca am ajuns la inceputul unei componente tare conexe ( Daca indexul este egal cu valoarea lowlink )
    if(indx[node] == lowlink[node]){
        vector<int> currentCtc;
        int nod = st.top();
        while(nod != node){
            st.pop();
            onStack[nod] = false;
            lowlink[nod] = indx[node];
            currentCtc.push_back(nod);
            nod = st.top();
        }
        st.pop();
        currentCtc.push_back(node);
        scc.push_back(currentCtc);
        onStack[node] = false;
        sccCount++;
    }
}

int main(){

    int n,m,x,y;
    f >> n >> m;
    adj_list.resize(n+1);
    for(int i = 0; i < m; ++i){
        f >> x >> y;
        adj_list[x].push_back(y);
    }
    indx = vector<int>(n + 1,-1);
    lowlink = vector<int>(n + 1,-1);
    onStack = vector<bool>(n + 1,false);
    for(int i = 1; i < n+1; ++i)
        if(indx[i] == -1)
            dfs(i);
    g<<sccCount<<"\n";
    for(auto x: scc) {
        for (auto y: x)
            g << y << " ";
        g<<"\n";
    }
}