Cod sursa(job #2796351)

Utilizator ChelaruPaulChelaru Paul ChelaruPaul Data 7 noiembrie 2021 22:30:25
Problema Componente tare conexe Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.93 kb
#include <iostream>
#include <vector>
#include <queue>
#include <fstream>
#include <stack>
#include <unordered_map>
#include <bitset>
using namespace std;

class Graph {
    //private attributes
    vector<vector<int>> edges;
    int numberOfNodes;

    //-------------------------------------

    //private methods
    void DFS(unordered_map<int, bool>&, int);
    void tarjan(int, int&, vector<int>&, vector<int>&, stack<int>&, unordered_map<int ,bool>&, unordered_map<int ,bool>&, vector<vector<int>>&);
public:
    Graph(int);
    ~Graph();
    void setEdge(int, int);
    vector<int> distance(int);
    int numberOfComponents();
    void displayEdges();
    vector<vector<int>> SCC();
};


int main()
{
    ifstream in("ctc.in");
    ofstream out("ctc.out");

    int numberOfNodes, numberOfEdges, from, to;

    in >> numberOfNodes >> numberOfEdges;

    auto* graph = new Graph(numberOfNodes);

    for (int countEdge = 1; countEdge <= numberOfEdges; countEdge++) {
        in >> from >> to;
        graph->setEdge(from, to);
    }

    vector<vector<int>> ccs = graph->SCC();
    out << ccs.size() << "\n";
    for(auto & cc : ccs) {
        for(int j : cc) {
            out << j << " ";
        }
        out << "\n";
    }

    return 0;
}

void Graph::displayEdges() {
    for(int node = 1; node <= numberOfNodes; node ++) {
        for (auto edge: edges[node])
            cout << node << " " << edge << endl;
    }
}

Graph::Graph(int numberOfNodes) {
    this->numberOfNodes = numberOfNodes;
    edges.resize(numberOfNodes + 1);
}

Graph::~Graph() = default;

void Graph::setEdge(int from, int to) {
    edges[from].push_back(to);
}

vector<int> Graph::distance(int from) {
    queue<int> queue;
    vector<int> visited(numberOfNodes + 1, -1);

    visited[from] = 0;
    queue.push(from);

    while (!queue.empty()) {
        int node = queue.front();
        for (auto edge : edges[node]) {
            if (visited[edge] == -1) {
                visited[edge] = visited[node] + 1;
                queue.push(edge);
            }
        }
        queue.pop();
    }

    return visited;
}

void Graph::DFS(unordered_map<int, bool> &visited, int start) {
    visited[start] = true;

    for(int &node : edges[start]) {
        if(!visited[node]) {
            DFS (visited ,node);
        }
    }
}

int Graph::numberOfComponents() {
    unordered_map<int ,bool> visited;
    int nrOfComp = 0;

    for(int node = 1; node <= numberOfNodes; node ++) {
        if(visited[node] == 0) {
            nrOfComp ++;
            DFS(visited, node);
        }
    }
    return nrOfComp;
}

vector<vector<int>> Graph::SCC() {
    stack<int> stack;
    vector<int> ids(numberOfNodes + 1), low_link(numberOfNodes + 1);
    vector<vector<int>> scc;
    unordered_map<int ,bool> visited, onStack;
    int id = 1;

    for(int node = 1; node <= numberOfNodes; node++){
        if(!visited[node])
            tarjan(node,  id, ids, low_link, stack, onStack, visited, scc);
    }
    return scc;
}

void Graph::tarjan(int start, int &id, vector<int> &ids, vector<int> &low_link,
                   stack<int>& stack, unordered_map<int ,bool> &onStack,
                   unordered_map<int, bool> &visited,vector<vector<int>> &scc) {
    ids[start] = id;
    low_link[start] = id;
    stack.push(start);
    visited[start] = true;
    onStack[start] = true;
    id++;

    for(auto node : edges[start]) {
        if(!visited[node]) {
            tarjan(node, id, ids, low_link, stack, onStack, visited, scc);
            low_link[start] = min(low_link[start], low_link[node]);
        } else {
            if (onStack[node]) {
                low_link[start] = min(low_link[start], low_link[node]);
            }
        }
    }

    if(low_link[start] == ids[start]){
        vector<int> cc;
        int ccNode;
        do{
            ccNode = stack.top();
            cc.push_back(ccNode);
            stack.pop();
            onStack[ccNode] = false;
        }while(ccNode != start);
        scc.push_back(cc);
    }
}