Cod sursa(job #2797426)

Utilizator ChelaruPaulChelaru Paul ChelaruPaul Data 9 noiembrie 2021 21:10:02
Problema Sortare topologica Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 7.01 kb
#include <iostream>
#include <vector>
#include <queue>
#include <fstream>
#include <stack>
#include <unordered_map>
#include <bitset>
using namespace std;

ifstream in("sortaret.in");
ofstream out("sortaret.out");

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>>&);
    void bicomponentsDFS(int, int, unordered_map<int, bool>, stack<int>,
            vector<int>, vector<int>, int&, vector<vector<int>>& );
    void topologicalSortingDFS(int,  vector<bool>&, stack<int>&);
public:
    Graph(int);
    ~Graph();
    void setEdge(int, int);
    vector<int> distance(int);
    int numberOfComponents();
    void displayEdges();
    vector<vector<int>> SCC();
    void biconnectedComponents();
    void topologicalSort();
};


int main() {
    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);
    }

    graph->topologicalSort();

    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);
    }
}

void Graph::bicomponentsDFS(int start, int parent, unordered_map<int, bool> visited,
                            stack<int> stack, vector<int> low_link, vector<int> link,
                            int& noOfBiconnectedComponents , vector<vector<int>>& biconnectedComponents) {
    link[start] = link[parent] + 1;
    low_link[start] = link[start];
    stack.push(start);
    visited[start] = true;

    for (auto node : edges[start]) {
        if (visited[node]) {
            cout << low_link[node] << " --- " << link[start] << endl;
            if(low_link[start] > link[node])
                low_link[start] = link[node];
            cout << low_link[node] << " ---- " << link[start] << endl;
        } else {
            bicomponentsDFS(node, start, visited, stack, low_link, link, noOfBiconnectedComponents, biconnectedComponents);

            cout << low_link[node] << " -- " << link[start] << endl;
            if(low_link[start] > low_link[node])
                low_link[start] = low_link[node];

            cout << low_link[node] << " - " << link[start] << endl;
            if(low_link[node] >= link[start]) {
                cout << " - ";
                noOfBiconnectedComponents ++;
                cout << noOfBiconnectedComponents << " - ";

                while(!stack.empty() && stack.top() != node) {
                    biconnectedComponents[noOfBiconnectedComponents].push_back(stack.top());
                    stack.pop();
                }
                biconnectedComponents[noOfBiconnectedComponents].push_back(stack.top());
                stack.pop();
                biconnectedComponents[noOfBiconnectedComponents].push_back(start);
            }
        }
    }
}

void Graph::biconnectedComponents() {
    int start = 1, parent = 0, noOfBiconnectedComponents = 0;
    unordered_map<int, bool> visited;
    stack<int> stack;
    vector<int> low_link(numberOfNodes + 1, 0), link(numberOfNodes + 1, 0);
    vector<vector<int>> biconnectedComponents;

    bicomponentsDFS(start , parent, visited, stack, low_link, link, noOfBiconnectedComponents, biconnectedComponents);

    cout << noOfBiconnectedComponents << "\n";
    for(int biconnectedComponent = 1; biconnectedComponent <= noOfBiconnectedComponents; biconnectedComponent++) {
        for(auto elements : biconnectedComponents[biconnectedComponent])
            cout << elements << " ";
        cout << "\n";
    }
}


void Graph::topologicalSortingDFS(int start, vector<bool>& visited, stack<int>& stack)
{
    visited[start] = true;
	for (int node : edges[start]) {
		if (!visited[node]) {
            topologicalSortingDFS(node, visited, stack);
		}
	}
    stack.push(start);
}

void Graph::topologicalSort()
{
    stack<int> stack;
    vector<bool> visited(numberOfNodes + 1, false);;

    for (int node = 1; node < visited.size(); node++) {
        if (!visited[node]) {
            topologicalSortingDFS(node, visited, stack);
        }
    }

    while (!stack.empty()) {
        out << stack.top()<<' ';
        stack.pop();
    }
}