Cod sursa(job #1957745)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 7 aprilie 2017 19:02:29
Problema Ciclu Eulerian Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.22 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <queue>
 
using namespace std;
 
class Graph {
  public:
    class Edge {
      public:
        Edge(const int _from, const int _to):
          from(_from),
          to(_to) {}
 
        int From() const {
            return from;
        }
 
        int To() const {
            return to;
        }
 
      private:
        int from, to;
    };
 
    static const int NIL = -1;
 
    Graph(const int _v = 0):
      v(_v),
      edges(vector<Edge>()),
      vertexEdges(vector< vector< pair<int, int> > >(_v, vector< pair<int, int> >())),
      degree(vector<int>(_v, 0)) {}
 
    int V() const {
        return v;
    }
 
    Edge GetEdge(const int e) const {
        return edges[e];
    }
 
    vector< pair<int, int> >::const_iterator EdgesBegin(const int x) const {
        return vertexEdges[x].begin();
    }
 
    vector< pair<int, int> >::const_iterator EdgesEnd(const int x) const {
        return vertexEdges[x].end();
    }
 
    void AddEdge(const Edge &e) {
        vertexEdges[e.From()].push_back(make_pair(e.To(), int(edges.size())));
        vertexEdges[e.To()].push_back(make_pair(e.From(), int(edges.size())));
        edges.push_back(e);
        ++degree[e.From()];
        ++degree[e.To()];
    }
 
    vector< pair<int, int> > GetEulerianCycle() const {
        if (!IsEulerianGraph())
            return vector< pair<int, int> >();
        vector<int> eulerDegree = degree;
        vector<bool> usedEdges = vector<bool>(int(edges.size()), false);
        vector< pair<int, int> > stack, cycle;
        int x = 0;
        do {
            Euler(x, eulerDegree, usedEdges, stack);
            x = stack.back().second;
            cycle.push_back(stack.back());
            stack.pop_back();
        } while (!stack.empty());
        reverse(cycle.begin(), cycle.end());
        return cycle;
    }
 
    bool IsEulerianGraph() const {
        for (int x = 0; x < v; ++x)
            if (degree[x] % 2 != 0)
                return false;
        return IsConnected();
    }
 
    bool IsConnected() const {
        vector<bool> used;
        BFS(0, used);
        for (int x = 0; x < v; ++x)
            if (!used[x])
                return false;
        return true;
    }
 
  private:
    int v;
    vector<Edge> edges;
    vector< vector< pair<int, int> > > vertexEdges;
    vector<int> degree;
 
    void BFS(const int source, vector<bool> &used) const {
        used = vector<bool>(v, false);
        queue<int> q;
        q.push(source);
        used[source] = true;
        for (; !q.empty(); q.pop()) {
            int x = q.front();
            used[x] = true;
            for (vector< pair<int, int> >::const_iterator e = vertexEdges[x].begin(); e != vertexEdges[x].end(); ++e) {
                if (!used[e->first]) {
                    q.push(e->first);
                    used[e->first] = true;
                }
            }
        }
    }
 
    int GetEulerDegree(const int x, vector<int> &eulerDegree, vector<bool> &usedEdges) const {
        for (; eulerDegree[x] > 0 && usedEdges[vertexEdges[x][eulerDegree[x] - 1].second]; --eulerDegree[x]);
        return eulerDegree[x];
    }
 
    void Euler(int x, vector<int> &eulerDegree, vector<bool> &usedEdges, vector< pair<int, int> > &stack) const {
        for (int y, e; GetEulerDegree(x, eulerDegree, usedEdges) > 0; x = y) {
            y = vertexEdges[x][GetEulerDegree(x, eulerDegree, usedEdges) - 1].first;
            e = vertexEdges[x][GetEulerDegree(x, eulerDegree, usedEdges) - 1].second;
            stack.push_back(make_pair(e, x));
            usedEdges[e] = true;
        }
    }
};
 
Graph G;
vector< pair<int, int> > Cycle;
 
void Solve() {
    Cycle = G.GetEulerianCycle();
}
 
void Read() {
    ifstream cin("ciclueuler.in");
    int v, e;
    cin >> v >> e;
    G = Graph(v);
    for (; e > 0; --e) {
        int x, y;
        cin >> x >> y;
        G.AddEdge(Graph::Edge(--x, --y));
    }
    cin.close();
}
 
void Print() {
    ofstream cout("ciclueuler.out");
    if (Cycle.empty()) {
        cout << "-1\n";
    } else {
        for (int i = 0; i < int(Cycle.size()); ++i)
            cout << Cycle[i].second + 1 << " ";
        cout << "\n";
    }
    cout.close();
}
 
int main() {
    Read();
    Solve();
    Print();
    return 0;
}