Cod sursa(job #3229905)

Utilizator Alex_Pogan_16Pogan Alexandru Mihail Alex_Pogan_16 Data 17 mai 2024 21:59:17
Problema Sortare topologica Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 7.42 kb
#include <iostream>
#include <vector>
#include <list>
#include <stack>
#include <fstream>
#include <algorithm>
#include <queue>

#define INFINITE 1000000

using namespace std;

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

typedef pair<int, vector<int>> sccPair;
vector<sccPair> sccs; 

int timestamp;

class Auxiliary {
    public:
        vector<int> initilialize_arrays(int number_of_vertices, int value) {
            vector<int> array(number_of_vertices + 1);
            for (int i = 0; i < number_of_vertices; i++) {
                array[i] = value;
            }

            return array;
        }
};

class Graph {
    private:
        int number_of_vertices;
        int number_of_edges;

        vector<vector<int>> adjacency_list;
        vector<int> parents;
        vector<int> discovery_times;
        vector<int> lowest_time;
        vector<int> internal_grade;

    public:
        Graph(int number_of_vertices, int number_of_edges, vector<vector<int>> adjacency_list) {
            Auxiliary auxiliary;

            this -> number_of_vertices = number_of_vertices;
            this -> number_of_edges = number_of_edges;
            this -> parents = auxiliary.initilialize_arrays(number_of_vertices + 1, -1);
            this -> discovery_times = auxiliary.initilialize_arrays(number_of_vertices + 1, INFINITE);
            this -> lowest_time = auxiliary.initilialize_arrays(number_of_vertices + 1, INFINITE);
            this -> internal_grade = auxiliary.initilialize_arrays(number_of_vertices + 1, 0);
            this -> adjacency_list = adjacency_list;
        }

        void addEdge(int src, int dest) {
            adjacency_list[src].push_back(dest);
            internal_grade[dest] ++;
        }
        void createGraph() {
            for (int i = 0; i < number_of_edges; i++) {
                int x, y;
                fin >> x >> y;
                addEdge(x, y);
            }
        }

        void dfs(int node, stack<int> &nodes_stack,vector<bool> &stack_member) {
            discovery_times[node] = ++timestamp;
            lowest_time[node] = discovery_times[node];
            nodes_stack.push(node);
            stack_member[node] = true;
            vector<int> ::iterator it;

            for (it = adjacency_list[node].begin(); it != adjacency_list[node].end(); it++) {
                int neighbour = *it;
                if (parents[neighbour] != -1) {
                    if (stack_member[neighbour] == true) {
                        lowest_time[node] = min(lowest_time[node], discovery_times[neighbour]);
                    }
                    continue;
                }

                parents[neighbour] = node;
                dfs(neighbour, nodes_stack, stack_member);

                lowest_time[node] = min(lowest_time[node], lowest_time[neighbour]);
            }

            if (lowest_time[node] == discovery_times[node]) {
                if (nodes_stack.empty() == false) {
                    vector<int> scc;
                    int x = nodes_stack.top();
                    nodes_stack.pop();
                    stack_member[x] = false;
                    scc.push_back(x);

                    // cout << x << " ";
                    while (x != node && !nodes_stack.empty()) {
                        x = nodes_stack.top();
                        scc.push_back(x);
                        // cout << x << " ";
                        stack_member[x] = false;
                        nodes_stack.pop();
                    }
                    sort(scc.begin(), scc.end());
                    sccs.push_back(make_pair(scc.size(), scc));

                }
            }
        }

        void tarjanSCC() {
            stack<int> nodes_stack;
            vector<bool> stack_member(number_of_vertices + 1);

            for (int i = 0; i <= number_of_vertices; i++) {
                stack_member[i] = false;
            }
            for (int i = 1; i <= number_of_vertices; i++) {
                if (this->parents[i] == -1) {
                    parents[i] = i;
                    dfs(i, nodes_stack, stack_member);
                }
            }
        }

        void solveTarjanSCCProblem() {
            createGraph();
            tarjanSCC();

            int minimum_pass = -999999, minimum_index = 0;
            int lower_limit = -999999;
            int index = 0;
            fout << sccs.size() << endl;
            for (int i = 0; i < sccs.size(); i++) {
                minimum_pass = 999999;
                for (int j = 0; j < sccs.size(); j++) {
                    if (minimum_pass >= sccs[j].second[0] && sccs[j].second[0] > lower_limit) {
                        minimum_pass = sccs[j].second[0];
                        minimum_index = j;
                    }
                }
                if (sccs[minimum_index].first > 0) {
                    fout << sccs[minimum_index].first << " ";
                    for (int j = 0; j < sccs[minimum_index].second.size(); j++) {
                        fout << sccs[minimum_index].second[j] << " ";
                    }
                    lower_limit = minimum_pass;
                    fout << endl;
                }

            }
        }

        void solveTarjanCVProblem() {
            
        }

        void topoSortDFS(int node, stack<int> &topoStack) {
    
            vector<int> ::iterator it;
            for (it = adjacency_list[node].begin(); it != adjacency_list[node].end(); it++) {
                int neigh = *it;
                if (parents[neigh] == -1) {
                    parents[neigh] = node;
                    topoSortDFS(neigh, topoStack); 
                }
            }

            topoStack.push(node);
        }

        void topologicalSortDFS() {
            createGraph();
            
            stack <int> topoStack;
            for (int i = 1; i <= number_of_vertices; i++) {
                if (parents[i] == -1) {
                    parents[i] = i;
                    topoSortDFS(i, topoStack);
                }
            }

            while (!topoStack.empty()) {
                fout << topoStack.top() << " ";
                topoStack.pop();
            }
        }

        void topologicalSortBFS() {
            createGraph();

            queue<int> topoQueue;
            for (int i = 1; i <= number_of_vertices; i++) {
                if (!internal_grade[i]) {
                    topoQueue.push(i);
                }
            }

            while (topoQueue.empty() == 0) {
                int current_node = topoQueue.front();
                topoQueue.pop();
                
                fout << current_node << " ";
                vector<int> ::iterator it;

                for (it = adjacency_list[current_node].begin(); it != adjacency_list[current_node].end(); it++) {
                    int neigh = *it;
                    internal_grade[neigh]--;
                    if (internal_grade[neigh] == 0) {
                        topoQueue.push(neigh);
                    }
                }
            }
        }
};

int main() {
    int number_of_vertices, number_of_edges;
    int task = 1;
    fin >> number_of_vertices >> number_of_edges;

    vector<vector<int>> adjacency_list(number_of_vertices + 1);
    Graph graph(number_of_vertices, number_of_edges, adjacency_list);

    if (task == 1) {
        graph.topologicalSortBFS();
        return 0;
    }

    graph.solveTarjanSCCProblem();   /* rezolva scc-urile folosind algoritmul lui tarjan */
    graph.solveTarjanCVProblem();
    graph.topologicalSortBFS();

    return 0;
}