#include <bits/stdc++.h>
using namespace std;
struct Edge {
  vector<tuple<int, int>> vertice;
};
class Graph {
 private:
  vector<Edge>* vertex;
  int numeroDeEdges, numeroDeVertices;
  vector<int>* mark;

 public:
  Graph(int vertices) {
    this->mark = new vector<int>(vertices);
    this->vertex = new vector<Edge>(vertices);
    this->numeroDeVertices = vertices;
    this->numeroDeEdges = 0;
  }
  int n() { return this->numeroDeVertices; }
  int e() { return this->numeroDeEdges; }
  void inserir(Graph* G, int vert, int position, int peso) {
    tuple<int, int> ligaPeso = make_tuple(position, peso);
    this->numeroDeEdges++;
    this->vertex->at(vert).vertice.push_back(ligaPeso);
  }
  void setMark(Graph* g, int vertice, int visitado) {
    this->mark->at(vertice) = visitado;
  }
  int getMark(Graph* G, int vertice) { return this->mark->at(vertice); }
  void dijkstra(Graph* G, int s, int long D[], int max, int P[]) {
    tuple<int, int, int> custoVp;
    priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>,
                   greater<tuple<int, int, int>>>
        vectorHeap;
    int infinito = max;
    for (int i = 0; i < G->n(); i++) {
      D[i] = infinito;
      P[i] = -1;
      G->setMark(G, i, 0);
    }
    int custo, vert, aresta, qualParent = 0, prox = 0, arestaAnterior = 0,
                             qualVert = 0, qualAresta = 0;
    custo = 0;
    aresta = 0;
    vert = 0;
    custoVp = make_tuple(0, 0, 0);
    vectorHeap.push(custoVp);
    D[0] = 0;
    P[0] = 0;
    for (int i = 0; i < G->n() - 1; i++) {
      bool verifica = false;
      do {
        if (vectorHeap.empty()) {
          verifica = true;
        } else {
          custoVp = vectorHeap.top();
          aresta = get<1>(custoVp);
          qualParent = get<2>(custoVp);
          custo = get<0>(custoVp);
          vectorHeap.pop();
        }
      } while (G->getMark(G, aresta) != 0 && verifica == false);
      G->setMark(G, aresta, 1);
      P[aresta] = qualParent;
      D[aresta] = custo;
      prox = aresta;
      int vectorHorizontal = 0, w = 0;
      while (w < G->n() &&
             vectorHorizontal < this->vertex->at(prox).vertice.size()) {
        w = get<0>(this->vertex->at(prox).vertice.at(vectorHorizontal));
        if ((G->getMark(G, w) != 1) &&
            (D[w] > D[aresta] + get<1>(this->vertex->at(aresta).vertice.at(
                                    vectorHorizontal)))) {
          P[w] = aresta;
          D[w] = D[aresta] +
                 get<1>(this->vertex->at(aresta).vertice.at(vectorHorizontal));
          custoVp = make_tuple(D[w], w, aresta);
          vectorHeap.push(custoVp);
        }
        vectorHorizontal++;
      }
    }
  }
};
int main() {
  int vertices = 0, edges = 0, loop = 0;
  scanf("%i %i", &vertices, &edges);
  int long distancias[vertices];
  int parentes[vertices];
  Graph* grafo = new Graph(vertices);
  while (loop < edges) {
    int v = 0, l = 0, peso = 0;
    scanf("%i %i %i", &v, &l, &peso);
    grafo->inserir(grafo, v - 1, l - 1, peso);
    grafo->inserir(grafo, l - 1, v - 1, peso);
    loop++;
  }
  grafo->dijkstra(grafo, 1, distancias, INT_MAX, parentes);
  vertices = vertices - 1;
  stack<int> resposta = stack<int>();
  bool noPath = false;
  if (parentes[vertices] == -1) {
    printf("-1");
  } else {
    do {
      resposta.push(vertices);
      vertices = parentes[vertices];
      if (vertices == -1) {
        noPath = true;
      }
    } while (vertices > 0 && noPath == false);
    printf("1 ");
    while (!resposta.empty()) {
      printf("%i ", resposta.top() + 1);
      resposta.pop();
    }
  }
  int t = 7;
}
