Cod sursa(job #2611697)

Utilizator alex.ivan1105Ivan Alexandru alex.ivan1105 Data 7 mai 2020 14:16:39
Problema Componente tare conexe Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.93 kb
#include <bits/stdc++.h>
using namespace std;

#define NMAX 50009

class Task {
public:
    void solve() {
        read_input();
        get_result();
        print_output();
    }

private:
    int n, m;

    vector<int> adj[NMAX];

    // graful transpus
    vector<int> adjT[NMAX];

    /* 
        Diferenta fata de DFS este ca retin un vector in care voi introduce fiecare nod DUPA ce il termin de parcurs.
        La finalul parcurgerii DFS il inversez pentru a avea ordinea corecta a nodurilor in functie de timpii de iesire. 
    */
    vector<int> topsort;

    vector<vector<int>> scc;

    void read_input() {
        ifstream fin("ctc.in");
        fin >> n >> m;

        for (int i = 1; i <= m; ++i) {
            int x, y;

            fin >> x >> y;

            adj[x].push_back(y);
            
            // construiesc graful transpus
            adjT[y].push_back(x);
        }

        fin.close();
    }

    void print_output() {
        ofstream fout("ctc.out");
        fout << scc.size() << endl;
        for (auto &vect : scc) {
            for (auto &it : vect) {
                fout << it << " ";
            }
            fout << endl;
        }

        fout.close();
    }

    void get_result() {
       kosaraju();
    }

    void kosaraju() {
        vector<int> visited(n + 1, 0);

        // ordonez nodurile in functie de timpii de iesire (ca la sortare topologica)
        for (int i = 1; i <= n; ++i) {
            if (!visited[i]) {
                dfs(i, visited, topsort);
            }
        }

        reverse(topsort.begin(), topsort.end());

        for (auto &it : topsort) {

            // refolosesc vectorul de vizitare. Daca un nod este marcat cu 1 => 
            // => este nevizitat; daca e marcat cu 0 => vizitat
            // tehnica ma ajuta sa nu mai fac inca o parcurgere de n elemente

            if (visited[it]) {
                vector<int> component;
                
                dfsT(it, visited, component);

                scc.push_back(component);
            }
        }
    }

    void dfs(int& node, vector<int>& visited, vector<int> &topsort) {
        visited[node] = 1;

        for (auto& it : adj[node]) {
            if (!visited[it]) {
                dfs(it, visited, topsort);
            }
        }

        // Introduc nodul in vector dupa ce am termiant vizitarea sa (am parcurs toti vecinii sai)
        topsort.push_back(node);
    }

    void dfsT(int& node, vector<int>& visited, vector<int> &component) {
        visited[node] = 0;
        component.push_back(node);

        for (auto& it : adjT[node]) {
            if (visited[it]) {
                dfsT(it, visited, component);
            }
        }
    }
};

int main() {
    // daca las linia asta citesc din fisier
    // assert(freopen("dfs.in",  "r", stdin)); 

    // daca las linia asta afisez in fisier
    // assert(freopen("dfs.out", "w", stdout));

    Task *task = new Task();
    task->solve();
    delete task;

    return 0;
}