Cod sursa(job #2930624)

Utilizator GeorgeNistorNistor Gheorghe GeorgeNistor Data 28 octombrie 2022 22:21:09
Problema Componente tare conexe Scor 90
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.21 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <stack>

using namespace std;

class Graph{
    vector<vector<int>> adj; // lista de adiacenta
    int V;                  // nr. de noduri
public:
    Graph(int V=0);
    Graph& operator=(const Graph& ob);
    void resize(int S);
    void addEdge(int v, int w);
    void print() const;
    friend ostream& operator<<(ostream& out, const Graph& ob);
    void printSCC();
    Graph getTranspose();
    void firstDFS(int v, bool visited[], stack<int>& Stack);
    void secondDFS(int v, bool visited[], vector<int>& SCC);
};

Graph::Graph(int V) {
    this->V = V;
    adj = vector<vector<int>>(V+1);
}

Graph& Graph::operator=(const Graph& ob){
    if(this != &ob) {
        this->V = ob.V;
        this->adj = vector<vector<int>>(V+1);
        int i = 0;
        for (const auto &v: ob.adj) {
            for (const auto &w: v)
                this->addEdge(w, i);
            i++;
        }
    }
    return *this;
}

void Graph::resize(int S) {
    adj = vector<vector<int>>(V+1);
}
void Graph::addEdge(int v, int w) {
    adj[v].push_back(w);
}

void Graph::print() const {
    int i = 0;
    for (const auto &v: adj) {
        cout << i << ": ";
        for (const auto &w: v)
            cout << w << " ";
        cout << endl;
        i++;
    }
}

ostream& operator<<(ostream& out, const Graph& ob){
    ob.print();
    return out;
}

Graph Graph::getTranspose(){
    Graph gT(V);
    int i = 0;
    for(const auto &v: adj) {
        for (const auto &w: v)
            gT.addEdge(i, w);
        i++;
    }
    return gT;
}

void Graph::firstDFS(int v, bool visited[], stack<int>& Stack){
    visited[v] = true;
    for(const auto &w: adj[v]){
        if(!visited[w])
            firstDFS(w, visited, Stack);
    }
    Stack.push(v);
}

void Graph::secondDFS(int v, bool visited[], vector<int>& SCC){
    SCC.push_back(v);
    visited[v] = true;
    for(const auto &w: adj[v])
        if(!visited[w])
            secondDFS(w, visited, SCC);
}

ofstream fout("ctc.out");
void Graph::printSCC() {
    vector<vector<int>> allSCC;
    stack<int> Stack;
    bool *visited = new bool[V+1];
    for(int i = 1; i <= V; i++)
        visited[i] = false;
    // Facem DFS pe g, iar in stiva vom avea nodurile in ordine inversa a momentului de finalizare
    for(int i = 1; i <= V; i++)
        if(!visited[i])
            firstDFS(i, visited, Stack);
    // Generam graful transpus al lui g
    Graph gT;
    gT = this->getTranspose();
    for(int i = 1; i <= V; i++)
        visited[i] = false;
    // Facem DFS pe gT, iar nodul de start este primul element din stiva care nu a fost vizitat
    while(!Stack.empty()){
        int v = Stack.top();
        Stack.pop();
        if(!visited[v]) {
            vector<int> SCC;
            gT.secondDFS(v, visited, SCC);
            allSCC.push_back(SCC);
        }
    }
    fout << allSCC.size() << endl;
    for(const auto &i: allSCC){
        for(const auto &v: i)
            fout << v << ' ';
        fout << endl;
    }
}

int main(){
    ifstream fin("ctc.in");
    int V, E;
    // Citim graful g
    fin >> V >> E;
    Graph g(V);
    for(int i = 0; i < E; i++) {
        int v, w;
        fin >> v >> w;
        g.addEdge(v, w);
    }
    g.printSCC();
    fout.close();
}