#include <fstream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std ;
const int NMAX = 500005 ;
ifstream fin("ciclueuler.in") ;
ofstream fout("ciclueuler.out") ;
vector <int> V[NMAX];
stack <int> S;
int N, M, U[NMAX];
inline void Euler()
{
///Am luat o stiva, stack, in care am introdus ca nod de pornire pe 1, unde voi si ajunge inapoi.
S.push(1) ;
///Ruleaza cat timp stiva e not null
while(!S.empty())
{
///Scot primul NOD din stiva
int nod = S.top() ;
///Verific daca are muchi ramase
if(V[nod].size())
{ ///Daca da, atunci iau primul nod si desigur o muchie.
int nod_nou = V[nod].back() ; ///asa il scot din vector.
V[nod].pop_back(); ///Il sterg din structura vector
V[nod_nou].erase(find(V[nod_nou].begin(), V[nod_nou].end(), nod)) ; ///Caut in nodul nou, nodul anterior si il sterg. AStfel algoritmul nu se intoarce in nodul anterior
S.push(nod_nou) ; ///Adaug la capatul stivei noul nod/
}
///Daca numai avem muchi in V[nod] atunci afisam nodul si il stergem din stiva
else
{
fout << nod << ' ' ;
S.pop() ;
}
}
}
int main()
{
fin >> N >> M ;
///Citesc datele de intrare, in vectorul U - retin gradul la fiecare NOD.
for(int i = 1 ; i <= M ; ++ i)
{
int x, y ;
fin >> x >> y ;
V[x].push_back(y) ;
V[y].push_back(x) ;
U[x] ++ ;
U[y] ++ ;
}
///Verific daca este Multigraf Eulerian, prima conditie, daca V[i].size() este diferit de 0 sau NODUL are un grad impar.
///IN cazula acesta afisez -1 SI RETURN 0
for(int i = 1 ; i <= N ; ++ i)
if(!V[i].size() || U[i] % 2 == 1)
{
fout << "-1\n" ;
return 0 ;
}
///Daca nu apelez functia EULER.
Euler() ;
fin.close() ;
fout.close() ;
return 0 ;
}