#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#define N 500001
#define oo 0x3f3f3f3f
using namespace std;
ifstream fin("ciclueuler.in");
ofstream fout("ciclueuler.out");
class Graph {
public:
int n; //nr de varfuri
int m; //nr de muchii
//vector <int> a[N];
//vector <int> a_t[N];
//pt roy floyd
//int matrice[N][N];
//pt apm
//vector<pair<pair<int, int>, int>> a_cost; //((nod1, nod2), cost) asa retin costul fiecarei muchii
//pt dijkstra
//vector<pair<int, int>>a_d[N];
//pt eulerian
vector<pair<int, int>>a_e[N];
Graph(int n, int m)
{
this->n = n;
this->m = m;
}
void Citire_orientat();
void Citire_neorientat();
void Citire_neorientat_cost(); //pt apm
void Citire_cost_D(); //pt dijkstra
void Citire_Floyd();
void Citire_Eulerian();
void Bellman_Ford(int x);
//------------tema1------------
//dfs
void DFS(int x, vector<bool>&viz, stack<int> &S);
void AfisareDfS();
//bfs
void BFS(int x);
//comp tare conexe
void DFS_T(int x, int ct, vector<bool>&viz_t, vector<int> c[N]);
void CompTConexe();
//sortare topologica
void SortTop();
//-------tema2---
//apm
void Kruskal();
int Find(int x, vector<int>&tata);
void Union(int rx, int ry, vector<int>&tata, vector<int>&h, int &nrm_apm);
//paduri de multimi disjuncte
void Disjoint();
//disjkstra
void Dijkstra(int x);
//------tema3-----
//roy-floyd
void Royfloyd();
//------tema4-----
void Eulerian();
};
//void Graph::Citire_orientat()
//{
// int i;
// int x, y;
//
// for (i = 0; i < m; i++)
// {
// fin >> x >> y;
// a[x].push_back(y);
// a_t[y].push_back(x);
//
// }
//}
//
//void Graph::Citire_neorientat()
//{
// int i;
// int x, y;
// for (i = 0; i < m; i++)
// {
// fin >> x >> y;
// a[x].push_back(y);
// a[y].push_back(x);
// }
//}
//
//void Graph::Citire_neorientat_cost()
//{
// int i;
// int x, y, z;
// for (i = 0; i < m; i++)
// {
// fin >> x >> y >> z;
// a_cost.push_back(make_pair(make_pair(x, y), z));
// // {{x,y},c}
//
// }
//
//}
//
//void Graph::Citire_cost_D()
//{
// int i;
// int x, y, z;
// for (i = 0; i < m; i++)
// {
// fin >> x >> y >> z;
// a_d[x].push_back(make_pair(y, z));
//
// }
//}
//
//void Graph::DFS(int x, vector<bool>& viz, stack<int>& S)
//{
// int i;
// viz[x] = 1;
// for (i = 0; i < a[x].size(); i++)
// if (!viz[a[x][i]])
// DFS(a[x][i], viz, S);
// S.push(x);
//
//
//}
//void Graph::AfisareDfS()
//{
// vector<bool> viz;
// stack<int> S;
// int nrc = 0;
//
// for (int i = 0; i <= n; i++)
// {
// viz.push_back(0);
//
// }
//
// for (int i = 1; i <= n; i++)
// if (!viz[i])
// {
// nrc++;
// DFS(i, viz, S);
// }
//
// fout << nrc;
//
//}
//void Graph::BFS(int x)
//{
// queue <int> q;
// vector<bool> viz;
// int cost[N];
// int k, i;
//
//
// for (int i = 0; i <= n; i++)
// viz.push_back(0);
//
// viz[x] = 1;
//
// cost[x] = 0;
// q.push(x);
//
// while (!q.empty())
// {
// k = q.front();
// for (i = 0; i < a[k].size(); i++)
// if (!viz[a[k][i]])
// {
// q.push(a[k][i]);
// viz[a[k][i]] = 1;
// cost[a[k][i]] = cost[k] + 1;
// }
//
// q.pop();
// }
//
// for (i = 1; i <= n; i++)
// if (viz[i] == 0)
// fout << -1 << " ";
// else fout << cost[i] << " ";
//
//
//
//}
//
//
//
//void Graph::SortTop()
//{
// int i;
// vector<bool> viz;
// stack<int> S;
//
// for (i = 0; i <= n; i++)
// viz.push_back(0);
//
// for (i = 1; i <= n; i++)
// if (!viz[i])
// DFS(i, viz, S);
// while (!S.empty())
// {
// fout << S.top() << " ";
// S.pop();
// }
//}
//
//
//void Graph::DFS_T(int x, int ct, vector<bool> &viz_t, vector<int>c[N])
//{
// int i;
// viz_t[x] = 1;
// c[ct].push_back(x); //pt fiecare nod, din ce comp tconexa face parte
// for (i = 0; i < a_t[x].size(); i++)
// if (viz_t[a_t[x][i]] == 0)
// DFS_T(a_t[x][i], ct, viz_t, c);
//}
//
//void Graph::CompTConexe()
//{
// int i, j, x, ct = 0;
// stack<int> S;
// vector<bool> viz_t;
//
// //comp tare conexe
// vector<int>c[N];
//
// for (int i = 0; i <= n; i++)
// viz_t.push_back(0);
//
//
// //parcurgerea grafului
//
// vector<bool> viz;
//
// for (i = 0; i <= n; i++)
// viz.push_back(0);
// for (i = 1; i <= n; i++)
// if (!viz[i])
// DFS(i, viz, S);
//
// //------------
//
// while (!S.empty())
// {
// x = S.top();
// S.pop();
// if (viz_t[x] == 0)
// {
// ct++;
// DFS_T(x, ct, viz_t, c);
// }
//
// }
// fout << ct << "\n";
// for (i = 1; i <= ct; i++)
// {
// for (j = 0; j < c[i].size(); j++)
//
// fout << c[i][j] << " ";
// fout << "\n";
// }
//
//}
//
//
//bool criteriu_sortare(const pair<pair<int, int>, int>& cost1, const pair<pair<int, int>, int >& cost2)
//{
// return cost1.second < cost2.second;
//}
//
//int Graph::Find(int x, vector<int>& tata)
//{
// if (x == tata[x])
// return x;
// return Find(tata[x], tata);
//
//
//}
//
//void Graph::Union(int x, int y, vector<int>&tata, vector<int>&h, int &nrm_apm)
//{
// int rx = Find(x, tata);
// int ry = Find(y, tata);
// //nrm_apm = 0;
//
// if (h[rx] < h[ry])
// {
// h[ry] += h[rx];
// tata[rx] = ry;
// nrm_apm++;
//
//
//
// }
// else
// {
// h[rx] += h[ry];
// tata[ry] = rx;
// nrm_apm++;
// }
//}
//void Graph::Kruskal()
//{
// int cost_total = 0;
// int i;
// int cx, cy;
// int nrm_apm;
// vector<int> tata;
// vector<int> h;
// vector<pair<int, int>>apm;
//
// nrm_apm = 0;
//
// for (int i = 0; i <= 2 * n; i++)
// {
// tata.push_back(0);
// h.push_back(0);
// }
//
// //pentru fiecare nod initializez vectorul de tata si de inaltime
// for (i = 0; i <= n; i++)
// {
// tata[i] = i;
// h[i] = 1;
//
// }
// //sortam vectorul de muchii ca sa facem apoi partea de greedy
// //folosim criteriul definit mai sus
//
// sort(a_cost.begin(), a_cost.end(), criteriu_sortare);
//
// for (i = 0; i < m; i++)
// {
// //gasesc cel mai indepartat stramos al fiecarui nod din muchia i
// cx = Find(a_cost[i].first.first, tata);
// cy = Find(a_cost[i].first.second, tata);
//
// if (cx != cy)
// {
// //e bun, inseamna ca nu formeaza cicluri deci o pastram in apm
//
// apm.push_back(make_pair(a_cost[i].first.first, a_cost[i].first.second));
//
// cost_total += a_cost[i].second;
// Union(a_cost[i].first.first, a_cost[i].first.second, tata, h, nrm_apm);
//
// }
//
//
// }
// fout << cost_total << "\n";
// fout << nrm_apm << "\n";
// for (i = 0; i < nrm_apm; i++)
// fout << apm[i].second << " " << apm[i].first << "\n";
//
//}
//
//
//
//
//
//void Graph::Disjoint()
//{
// int i, x, y, operatie;
// vector<int> tata;
// vector<int> h;
// int nrm = 0;
//
// for (int i = 0; i <= 2*n; i++)
// {
// tata.push_back(0);
// h.push_back(0);
// }
//
// for (i = 0; i <= n; i++)
// {
// tata[i] = i;
// h[i] = 1;
// }
//
// for (i = 0; i < m; i++)
// {
// fin >>operatie>>x >> y;
//
// if (operatie == 1)
// {
// Union(x, y, tata, h, nrm);
// }
// else {
// if (Find(x, tata) == Find(y, tata))
// fout << "DA" << "\n";
// else fout << "NU" << "\n";
// }
// }
//}
//
//void Graph::Dijkstra(int s)
//{
// int i, j , v;
// int f[N], d[N];
// priority_queue<pair<int, int> > pq;
//
// //le setam pe toate ca fiind neexplorate
// for (i = 1; i <= n; i++)
// d[i] = oo;
// d[s] = 0;
// f[s] = 1;
//
// //bagam primul nod in pq
// pq.push(make_pair(0, s)); //pq compara prima poz si vreau sa le sorteze dupa cost
//
// while (!pq.empty())
// {
// int u = pq.top().second;
// pq.pop();
//
//
// for (auto i : a_d[u]) //a_d[x] = (nod adiacent, cost muchia(x-nod_adiacent) )
// {
// if (d[u] + i.second < d[i.first])
// {
// d[i.first] = d[u] + i.second;
// pq.push(make_pair(d[i.first], i.first));
// }
// }
//
//
//
// }
// for (i = 1; i <= n; i++)
// if (i != s)
// {
// if (d[i] != oo)
// fout << d[i] << " ";
// else fout << 0 << " ";
// }
//
//
//}
//
////void Graph::Bellman_Ford(int s)
////{
//// int i, j;
//// bool neg = 0;
//// int viz[N];
//// for (i = 1; i <= n; i++)
//// d[i] = oo;
//// d[s] = 0;
//// f[s] = 1;
//// //bagam primul nod in pq
//// pq.push(make_pair(0, s)); //pq compara prima poz si vreau sa le sorteze dupa cost
//// while (!pq.empty() && !neg)
//// {
//// int u = pq.top().second;
//// pq.pop();
//// f[s] = 0;
////
//// for (auto i : a_d[u]) //a_d[x] = (nod adiacent, cost muchia(x-nod_adiacent) )
//// {
//// if (d[u] + i.second < d[i.first])
//// {
//// d[i.first] = d[u] + i.second;
//// if (!f[u])
//// {
//// pq.push(make_pair(d[i.first], i.first));
//// f[u] = 1;
//// }
//// viz[u]++;
//// if (viz[u] >= n)
//// {
//// neg = 1;
//// break;
//// }
//// }
//// }
//// }
////
//// if (!neg)
//// {
//// for (i = 2; i <= n; i++)
//// fout << d[i] << " ";
////
//// }
//// else fout << "Ciclu negativ!";
////
////}
////
//void Graph::Citire_Floyd()
//{
// int i, j;
// for (i = 1; i <= n; i++)
// for (j = 1; j <= n; j++)
// {
// fin >> matrice[i][j];
// if (i != j)
// if (!matrice[i][j])
// matrice[i][j] = oo;
// }
//
//
//}
//void Graph::Royfloyd()
//{
// int i, j, k;
// for (k = 1; k <= n; k++)
// for (i = 1; i <= n; i++)
// for (j = 1; j <= n; j++)
// if (matrice[i][j] > matrice[i][k] + matrice[k][j])
// matrice[i][j] = matrice[i][k] + matrice[k][j];
//
// for (i = 1; i <= n; i++)
// {
// for (j = 1; j <= n; j++)
// if (matrice[i][j] != oo)
// fout << matrice[i][j] << " ";
// else fout << 0;
// fout << "\n";
// }
//}
void Graph::Citire_Eulerian()
{
int i, x, y;
for (i = 0; i < m; i++)
{
fin >> x >> y;
a_e[x].push_back(make_pair(y, i));
a_e[y].push_back(make_pair(x, i));
}
}
int CheckEulerian(vector<pair<int, int>>a_e[N], int n)
{
int i,ct = 0;
for (i = 1; i <= n; i++)
if (a_e[i].size() % 2 == 1)
return 0;
return 1;
}
void Solve_Euler(vector<pair<int, int>>a_e[N], int n, int k, vector<int> euler, stack<int> S)
{
int i, j;
vector<bool> viz;
for (i = 0; i <= n + 5; i++)
viz.push_back(0);
S.push(k);
while (!S.empty())
{
int x = S.top();
if (a_e[x].size())
{
int e = a_e[x].back().first;
int muchie = a_e[x].back().second;
a_e[x].pop_back();
if (!viz[muchie])
{
viz[muchie] = 1;
S.push(e);
}
}
else
{
S.pop();
fout << x << " ";
}
}
}
void Graph::Eulerian()
{
int i, j, x, y;
stack<int> S;
vector<int> euler;
if (CheckEulerian(a_e, n))
{
Solve_Euler(a_e, n, 1, euler, S);
//fout << 1;
}
else fout << -1;
}
int main()
{
int n, m;
fin >> n >> m;
Graph g(n, m);
g.Citire_Eulerian();
g.Eulerian();
return 0;
}