Cod sursa(job #2257398)

Utilizator cosmin.pascaruPascaru Cosmin cosmin.pascaru Data 10 octombrie 2018 00:29:36
Problema Ciclu Eulerian Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 6.12 kb
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <array>
#include <algorithm>
#include <vector>
#include <stack>
#include <set>
#include <assert.h>
#include <queue>
#include <chrono>
#include <memory>
#include <cstring>
#include <list>
#include <unordered_set>

using LL = long long;
using ULL = int long long;

const std::string _problemName = "ciclueuler";

#define USE_FILES

#ifdef USE_FILES

namespace std {
std::ifstream fin(_problemName + ".in");
std::ofstream fout(_problemName + ".out");
}

#define cin fin
#define cout fout
#endif

using SimpleGraphBase = std::vector< std::vector<int> >;
class SimpleGraph : public SimpleGraphBase {

public:

    SimpleGraph(int n) : SimpleGraphBase(n) {}

    void addEdge(int x, int y) {
        base()[x].push_back(y);
        base()[y].push_back(x);
    }

    bool hasEulerianCycle() {
        for (const auto& nodeNeighbours : base()) {
            if (nodeNeighbours.empty() || nodeNeighbours.size() % 2 != 0) {
                return false;
            }
        }
        return true;
    }

    bool exists(int edge) {
        return edge != -1;
    }

    void dfs(int node) {
        for (auto& edge : base()[node]) {
            if (exists(edge)) {
                int neighbour = edge;

                edge = -1;
                auto it = std::find(base()[neighbour].begin(), base()[neighbour].end(), node);
                *it = -1;

                dfs(neighbour);

                (*eulerianCycle).push_back(node);
            }
        }
    }

    void buildEulerianCycle(std::vector<int>& eulerianCycle) {
        this->eulerianCycle = &eulerianCycle;

        dfs(0);
        eulerianCycle.emplace_back(eulerianCycle.front());
    }

private:

    SimpleGraphBase& base() {
        return (*this);
    }

    std::vector<int>* eulerianCycle;

};

using VectorRemoveGraphBase = std::vector< std::vector<int> >;
class VectorRemoveGraph : public VectorRemoveGraphBase {

public:

    VectorRemoveGraph(int n) : VectorRemoveGraphBase(n) {}

    void addEdge(int x, int y) {
        base()[x].push_back(y);
        base()[y].push_back(x);
    }

    bool hasEulerianCycle() {
        for (const auto& nodeNeighbours : base()) {
            if (nodeNeighbours.size() % 2 != 0) {
                return false;
            }
        }
        return true;
    }

    bool exists(int edge) {
        return edge != -1;
    }

    void dfs(int node) {
        for (auto& edge : base()[node]) {
            if (exists(edge)) {
                int neighbour = edge;

                edge = -1;
                auto it = std::find(base()[neighbour].begin(), base()[neighbour].end(), node);
                base()[neighbour].erase(it);

                dfs(neighbour);

                (*eulerianCycle).push_back(node);
            }
        }
    }

    void buildEulerianCycle(std::vector<int>& eulerianCycle) {
        this->eulerianCycle = &eulerianCycle;

        dfs(0);
        eulerianCycle.emplace_back(eulerianCycle.front());
    }

private:

    VectorRemoveGraphBase& base() {
        return (*this);
    }

    std::vector<int>* eulerianCycle;

};

using LinkedListGraphBase = std::vector< std::pair< std::list<int>, int> >;
class LinkedListGraph : public LinkedListGraphBase {

public:

    LinkedListGraph(int n) : LinkedListGraphBase(n) {}

    void addEdge(int x, int y) {
        base()[x].first.push_back(y);
        base()[x].second++;
        base()[y].first.push_back(x);
        base()[y].second++;
    }

    bool hasEulerianCycle() {
        for (const auto& nodeNeighbours : base()) {
            if (nodeNeighbours.second == 0 || nodeNeighbours.second % 2 != 0) {
                return false;
            }
        }
        return true;
    }

    bool exists(int edge) {
        return true;
    }

    void dfs(int node) {
        while (!base()[node].first.empty()) {
            auto it = base()[node].first.begin();
            int neighbour = *it;

            base()[node].first.erase(it);

            auto it2 = std::find(base()[neighbour].first.begin(), base()[neighbour].first.end(), node);
            base()[neighbour].first.erase(it2);

            dfs(neighbour);

            (*eulerianCycle).push_back(node);
        }
    }

    void buildEulerianCycle(std::vector<int>& eulerianCycle) {
        this->eulerianCycle = &eulerianCycle;

        dfs(0);
        eulerianCycle.emplace_back(eulerianCycle.front());
    }

private:

    LinkedListGraphBase& base() {
        return (*this);
    }

    std::vector<int>* eulerianCycle;

};


using UnorderedSetGraphBase = std::vector< std::unordered_multiset<int> >;
class UnorderedSetGraph : public UnorderedSetGraphBase {

public:

   UnorderedSetGraph(int n) : UnorderedSetGraphBase(n) {}

   void addEdge(int x, int y) {
       base()[x].insert(y);
       base()[y].insert(x);
   }

   bool hasEulerianCycle() {
       for (const auto& nodeNeighbours : base()) {
           if (nodeNeighbours.empty() || nodeNeighbours.size() % 2 != 0) {
               return false;
           }
       }
       return true;
   }


   void dfs(int node) {
       while (!base()[node].empty()) {
            auto it = base()[node].begin();
            int neighbour = *it;

            base()[node].erase(it);

            auto it2 = base()[neighbour].find(node);
            base()[neighbour].erase(it2);

            dfs(neighbour);

            (*eulerianCycle).push_back(node);
        }
   }

   void buildEulerianCycle(std::vector<int>& eulerianCycle) {
       this->eulerianCycle = &eulerianCycle;

       dfs(0);
       eulerianCycle.emplace_back(eulerianCycle.front());
   }

private:

   UnorderedSetGraphBase& base() {
       return (*this);
   }

   std::vector<int>* eulerianCycle;

};

int main() {


    int n, m;
    std::cin >> n >> m;

    UnorderedSetGraph graph(n);

    while (m--) {
        int x, y;
        std::cin >> x >> y;
        --x, --y;
        graph.addEdge(x, y);
    }

    if (!graph.hasEulerianCycle()) {
        std::cout << "-1\n";
        return 0;
    }

    std::vector<int> eulerianCycle;
    graph.buildEulerianCycle(eulerianCycle);

    for (const auto node : eulerianCycle) {
        std::cout << node + 1 << ' ';
    }
    std::cout << '\n';

    return 0;
}