Cod sursa(job #2925578)

Utilizator liviu_gheorghe1234Liviu Gheorghe liviu_gheorghe1234 Data 15 octombrie 2022 18:48:27
Problema Componente tare conexe Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.72 kb
#include <bits/stdc++.h>
using namespace std; 


vector<int> finishingTime;

bool defaultComparator(int a, int b) {
    return finishingTime[a] > finishingTime[b];
}


ifstream fin("ctc.in");
ofstream fout("ctc.out");
std::stringstream ssResult;

class Graph {

    private:

        vector<vector<int>> adjList; 
        int N; 
        int M; 
        Graph* transposed = nullptr;
        bool modifiedSinceLastTransposal; 
        int numberOfVisitedNodes; 

        void _DFS(int currentNode, bool printOutput = false) {


            if(printOutput) {
                ssResult << currentNode << " ";
            }

            visited[currentNode] = true;

            for(int j = 0; j < adjList[currentNode].size();j++) {
                if(!visited[adjList[currentNode][j]]) {
                    _DFS(adjList[currentNode][j], printOutput);
                }
            }

            finishingTime[currentNode] = ++numberOfVisitedNodes;

        }

    public:

        vector<bool> visited; 

        Graph(int N, int M) {
            this->N = N;
            this->M = M;
            this->adjList = vector<vector<int>>(N+1);
            this->modifiedSinceLastTransposal = true;
            this->numberOfVisitedNodes = 0;
            this->visited = vector<bool>(N+1);
        }

        void addEdge(int x, int y) {


            if(std::find(adjList[x].begin(), adjList[x].end(), y) == adjList[x].end()) {
                this->adjList[x].push_back(y);
            }
            this->modifiedSinceLastTransposal = true;
        }

        void printAdjList() {
            for(int i = 1; i <= N; i++) {
                for(int j = 0; j < adjList[i].size(); j++) {
                    cout << adjList[i][j] << " ";
                }
                cout << "\n";
            }
        }

        Graph& getTransposed() {

            if(transposed == nullptr || modifiedSinceLastTransposal) {

            if(transposed != nullptr) {
                delete transposed;
            }

            transposed = new Graph(N, M);

                for(int i = 1; i <= N; i++) {
                    for(int j = 0; j < adjList[i].size(); j++) {
                        transposed->addEdge(adjList[i][j], i);
                    }
                }
            
                modifiedSinceLastTransposal = false;
            }

            return *transposed;
        }

        void DFS(int currentNode, bool reinitializeInternalVars = true, bool(*comparator) (int, int) = defaultComparator, bool printOutput=false) {
            
            // This is a wrapper method over the actual DFS implementation in order to remove the necessity of re-initializing this by the function caller
            // every time a DFS is made

            // Re-initialize the visited array and the number of visited nodes


            if(reinitializeInternalVars) {
                numberOfVisitedNodes = 0;
                std::fill(visited.begin(), visited.end(), 0);
            }

            // Sort the adjacency lists of every node with respect to the provided comparator

            for(int i = 1; i <= N; i++) {
                sort(adjList[i].begin(), adjList[i].end(), comparator);
            }

            _DFS(currentNode, printOutput);
        }

        void computeDFSFinishingTimes() {

            numberOfVisitedNodes = 0;
            std::fill(visited.begin(), visited.end(), 0);

            for(int i = 1; i <= N;i++) {
                if(!visited[i]) {
                    DFS(i, false, defaultComparator, false);
                }
            }

            // cout << "\nFinishing times are the following: ";
            // for(int i = 1; i <= N;i++) {
            //     cout << finishingTime[i] << " ";
            // }

            // cout << "\n";
        }
};

int main() {

    int N, M; 
    int x, y; 

    fin >> N >> M;
    finishingTime = vector<int> (N+1);

    Graph G {N, M};

    for(int i = 0; i<M;i++) {
        fin >> x >> y;
        G.addEdge(x, y);
    }

    Graph GT = G.getTransposed();


    // cout << "DFS for graph G:\n";
    G.computeDFSFinishingTimes();
    // cout << "\n";

    //cout << "DFS finishing times for graph G are: ";
    // for(int i = 1; i<=N; i++) {
    //     cout << finishingTime[i] << " ";    
    // }

    // cout << "\n";

    // // DFS for transposed graph 


    // cout << "DFS for transposed graph:\n";


    int nrComp = 0;



    vector<int> listOfNodes = vector<int>(N+1);

    for(int i = 1; i<=N;i++) {
        listOfNodes[N - finishingTime[i] + 1] = i;
    }


    for(int i = 1; i<=N; i++) {
        if(!GT.visited[listOfNodes[i]]) {
            nrComp++;
            GT.DFS(listOfNodes[i], false, defaultComparator, true);
            ssResult << "\n";
        }
    }

    fout << nrComp << "\n";

    fout << ssResult.rdbuf();

    return 0;
}