Cod sursa(job #2947654)

Utilizator dey44andIoja Andrei-Iosif dey44and Data 26 noiembrie 2022 15:49:04
Problema Ciclu Eulerian Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.82 kb
#include <bits/stdc++.h>

#define forRange(a, b) for(int32_t it = a; it < b; ++it)

using namespace std;

class Graph {
private:
    int32_t nodes, edges;
    unordered_map < int32_t, int32_t > *vertices;
    vector < int32_t > father_of;
    void reunite(int32_t node1, int32_t node2) {
        father_of[get_father(node1)] = get_father(node2);
    }
public:
    Graph(int32_t nodes, int32_t edges) {
        assert(nodes > 0 && edges >= 0);
        this -> nodes = nodes;
        forRange(0, (nodes + 1)) {
            father_of.push_back(it);
        }
        this -> edges = edges;
        this -> vertices = new unordered_map < int32_t, int32_t >[this-> nodes + 1];
    }
    Graph(const Graph& graph) {
        this -> nodes = graph.nodes;
        this -> edges = graph.edges;

        this -> vertices = new unordered_map< int32_t, int32_t >[this -> nodes + 1];
        forRange(0, (this -> nodes + 1)) {
            this -> vertices[it] = graph.vertices[it];
        }

        this -> father_of = graph.father_of;
    }
    void add_edge(int32_t x, int32_t y) {
        this -> vertices[x][y]++;
        this -> vertices[y][x]++;
        reunite(x, y);
    }
    void remove_neighbour_of(int32_t node, int32_t neighbour) {
        if(node != neighbour) {
            if(this->vertices[node][neighbour] > 1) {
                this->vertices[node][neighbour]--;
                this->vertices[neighbour][node]--;
            } else {
                this -> vertices[node].erase(neighbour);
                this -> vertices[neighbour].erase(node);
            }
        } else {
            if(this->vertices[node][neighbour] > 2) {
                this->vertices[node][neighbour]--;
                this->vertices[neighbour][node]--;
            } else {
                this -> vertices[node].erase(neighbour);
                this -> vertices[neighbour].erase(node);
            }
        }

    }
    int32_t get_father(int32_t node) {
        if(node == father_of[node]) return node;
        father_of[node] = get_father(father_of[node]);
        return father_of[node];
    }
    int32_t get_neighbour(int32_t node) const {
        if(!this -> vertices[node].empty())
            return this->vertices[node].begin()->first;
        return -1;
    }
    int32_t get_nodes_number() const {
        return this->nodes;
    }
    int32_t get_neighbours_counter_of(int32_t node) const {
        int32_t answer = 0;
        for(auto x : this->vertices[node]) {
            answer += x.second;
        }
        return answer;
    }
    vector < int32_t > get_fathers() const {
        return this->father_of;
    }
};

class GraphManager {
public:
    static Graph read_graph(const string &fileName) {
        ifstream in(fileName);

        int32_t nodes, edges;
        in >> nodes >> edges;
        Graph graph(nodes, edges);
        forRange(0, edges) {
            int32_t node1, node2;
            in >> node1 >> node2;
            graph.add_edge(node1, node2);
        }
        in.close();

        return graph;
    }

    static bool even_grade(const Graph &graph) {
        forRange(1, (graph.get_nodes_number() + 1)) {
            if(graph.get_neighbours_counter_of(it) & 1)
                return false;
        }
        return true;
    }

    static bool is_connected(Graph &graph) {
        forRange(1, (graph.get_nodes_number() + 1)) {
            if(graph.get_father(1) != graph.get_father(it))
                return false;
        }

        return true;
    }

    static vector < int32_t > generate_euler_cycle(Graph &graph) {
        vector < int32_t > cycle;

        stack < int32_t > stack_nodes;
        stack_nodes.push(1);

        while(!stack_nodes.empty()) {
            int32_t node = stack_nodes.top();

            if(graph.get_neighbour(node) != -1) {
                int32_t neighbour = graph.get_neighbour(node);
                graph.remove_neighbour_of(node, neighbour);
                stack_nodes.push(neighbour);
            } else {
                stack_nodes.pop();
                cycle.push_back(node);
            }
        }
        cycle.pop_back();

        return cycle;
    }
};

class PrintManager {
public:
    static void print_vector(const vector < int32_t > &array, const string &fileName) {
        ofstream out(fileName);

        for(auto v : array) {
            out << v << " ";
        }

        out.close();
    }

    static void print_value(int32_t value, const string &fileName) {
        ofstream out(fileName);

        out << value;

        out.close();
    }
};

int main() {
    Graph graph = GraphManager::read_graph("ciclueuler.in");

    if(GraphManager::is_connected(graph) && GraphManager::even_grade(graph)) {
        vector < int32_t > cycle = GraphManager::generate_euler_cycle(graph);
        PrintManager::print_vector(cycle, "ciclueuler.out");
    } else {
        PrintManager::print_value(-1, "ciclueuler.out");
    }



    return 0;
}