#include <fstream>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_set>
using namespace std;
// Clasa pentru graf
class graf {
protected:
int noduri, muchii;
vector < vector < int >> adiacenta;
public:
// Constructor cu matrice de adiacenta data
graf(vector < vector < int >> listaAdiacenta, int noduri, int muchii): adiacenta(listaAdiacenta), noduri(noduri), muchii(muchii) {};
// Constructor fara matrice de adiacenta, se cu initalizeaza una goala
graf(int noduri, int muchii): adiacenta(noduri + 1), noduri(noduri), muchii(muchii) {};
vector < int > bfs(int);
int dfs();
};
// Clasa pentru graf neorientat
class graf_neorientat : public graf{
private:
void dfsbiconex(int, vector < int >&, vector < int >&, stack < pair < int, int >>&, int&, vector < string >&);
void dfsCriticalConnections(int tata, vector < int >&, vector < int >&, int&, vector < vector < int >>&, vector < int >&);
int darbbfs(int, int&);
public:
graf_neorientat(vector < vector < int >> listaAdiacenta, int noduri, int muchii): graf(listaAdiacenta, noduri, muchii) {};
graf_neorientat(int noduri, int muchii): graf(noduri, muchii) {};
friend istream& operator>>(istream&, graf_neorientat&);
vector < string > biconex();
vector < vector < int >> criticalConnections();
int darb();
bool checkEuler();
vector<int> euler(vector<unordered_set<int>>);
};
// Citire pentru graf neorientat
istream& operator>>(istream& in, graf_neorientat& g) {
for (int i = 0; i < g.muchii; i++) {
int aux1, aux2;
in >> aux1 >> aux2;
g.adiacenta[aux1].push_back(aux2);
g.adiacenta[aux2].push_back(aux1);
}
return in;
}
// Functie care verifica daca un graf neorientat poate fi euler
bool graf_neorientat::checkEuler(){
for (int i = 1; i<adiacenta.size(); i++) {
if (adiacenta[i].size() % 2 != 0) {
return 0;
}
}
return 1;
}
// Functie care returneaza ciclul euler al unui graf eulerian
vector<int> graf_neorientat :: euler(vector<unordered_set<int>> adiacenta)
{
stack<int> curent;
vector<int> raspuns;
curent.push(1);
while (!curent.empty()) {
int nod = curent.top();
if (adiacenta[nod].size()) {
int nod1 = *begin(adiacenta[nod]);
curent.push(nod1);
adiacenta[nod].erase(nod1);
adiacenta[nod1].erase(nod);
}
else {
raspuns.push_back(nod);
curent.pop();
}
}
return raspuns;
}
void eulerDriver() {
// https://infoarena.ro/problema/ciclueuler
// Citire
ifstream in("ciclueuler.in");
ofstream out("ciclueuler.out");
int n, m;
in >> n >> m;
graf_neorientat x(n, m);
vector<unordered_set<int>> adiacenta(n+1);
for (int i = 0; i < m; i++) {
int aux1, aux2;
in >> aux1 >> aux2;
adiacenta[aux1].insert(aux2);
adiacenta[aux2].insert(aux1);
}
if (!x.checkEuler()) {
out << -1;
return;
}
vector<int> raspuns = x.euler(adiacenta);
for (int i = 0; i < raspuns.size() - 1; i++) {
out << raspuns[i] << " ";
}
}
int main() {
// Se apeleaza functia corespunzatoare problemei
eulerDriver();
return 0;
}