#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
ifstream in("ciclueuler.in");
ofstream out("ciclueuler.out");
const int inf = 1<<30;
class Graf
{
private:
static const int nmax = 100001;
static const int mmax = 500001;
bool orientat;
int nrNoduri;
vector <int> listaAdiacenta[nmax];
vector <pair <int, int>> listaAdiacentaCost[nmax];
public:
Graf(int nrNoduri = 0, bool orientat = false);
void adaugaMuchie(int, int);
void adaugaMuchieCost(int, int, int);
void citireMuchii(int);
void citireMuchiiCost(int);
vector<int> BFS(int);
void DFS(int, bool*);
int nrComponenteConexe();
void DFSStiva(int nodcurent, bool *, stack<int> &);
void sortareTopologica();
void TarjanCTC(int&, int, int*, int*, bool*, stack <int> &, vector<vector<int>> &);
void CTC();
void TarjanBC(int&, int, int, int*, int*, stack <int>&, vector<vector<int>>&);
void BC();
void TarjanMC(int&, int, int, int*, int*, vector<pair<int,int>>&);
void MC();
vector <int> citireHakimi();
bool Hakimi(vector <int>);
vector <int> Dijkstra(int);
pair<int, vector <pair <int, int>>> Prim(int);
vector <int> BellmanFord(int);
void reuniune(int, int, vector<int>&, vector<int>&);
int gasire(int, vector<int>&);
void verifica(int, int, vector<int>&);
void paduri();
void RoyFloyd(int[][nmax]);
void rezolvareRoyFloyd();
int diametru();
bool BFSFMax(int**, int*, int, int);
int EdmondsKarp(int**, int, int);
void citireAfisareEdmondsKarp(int, int, int);
void cicluEuler(int, bool*, vector<int>&);
void rezolvareEuler();
};
Graf :: Graf(int nrNoduri, bool orientat) : nrNoduri(nrNoduri), orientat(orientat)
{
this->nrNoduri = nrNoduri;
this->orientat = orientat;
}
void Graf:: adaugaMuchie(int nod1, int nod2)
{
listaAdiacenta[nod1].push_back(nod2);
}
void Graf::adaugaMuchieCost(int nod1, int nod2, int cost)
{
listaAdiacentaCost[nod1].push_back(make_pair(nod2, cost));
}
void Graf::citireMuchii(int nrMuchii)
{
int nod1, nod2;
for(int i = 0; i < nrMuchii; i++)
{
in >> nod1 >> nod2;
listaAdiacenta[nod1].push_back(nod2);
if(!orientat)
{
listaAdiacenta[nod2].push_back(nod1);
}
}
}
void Graf::citireMuchiiCost(int nrMuchii)
{
int nod1, nod2, cost;
for(int i = 0; i < nrMuchii; i++)
{
in >> nod1 >> nod2 >> cost;
adaugaMuchieCost(nod1, nod2, cost);
if(!orientat)
{
adaugaMuchieCost(nod2, nod1, cost);
}
}
}
void Graf::cicluEuler(int nodStart, bool *vizitat, vector<int>& ciclu)
{
stack <int> stiva;
stiva.push(nodStart);
while(!stiva.empty())
{
int nodCurent = stiva.top();
if(!listaAdiacentaCost[nodCurent].empty())
{
int vecin = listaAdiacentaCost[nodCurent].back().first;
int nrMuchie = listaAdiacentaCost[nodCurent].back().second;
listaAdiacentaCost[nodCurent].pop_back();
if(!vizitat[nrMuchie])
{
vizitat[nrMuchie] = true;
stiva.push(vecin);
}
}
else
{
ciclu.push_back(nodCurent);
stiva.pop();
}
}
}
void Graf::rezolvareEuler()
{
bool vizitat[mmax];
vector <int> ciclu;
for(int i = 0; i <= nrNoduri; i++)
{
if(listaAdiacentaCost[i].size() % 2)
{
out << -1;
return;
}
}
cicluEuler(1, vizitat, ciclu);
for(int i = 0; i < ciclu.size() - 1; i++)
{
out << ciclu[i] << " ";
}
}
int main()
{
int n, m;
in >> n >> m;
Graf g(n, false);
int nod1, nod2;
for(int i = 0; i < m; i++)
{
in >> nod1 >> nod2;
g.adaugaMuchieCost(nod1, nod2, i);
g.adaugaMuchieCost(nod2, nod1, i);
}
g.rezolvareEuler();
return 0;
}