#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
  int to;
  int len;
} edge;

typedef struct {
  edge* vec;
  int size;
  int max_size;
} vector;

vector* vector_new() {
  vector* vec = calloc(1, sizeof(*vec));
  return vec;
}

void vector_free(vector* vec) {
  free(vec->vec);
  free(vec);
}

void vector_push(vector* vec, int b, int w) {
  if (vec->size == vec->max_size) {
    // we need to allocate more memory
    int new_size = (vec->size == 0 ? 10 : 2 * vec->size);
    edge* new_vec = calloc(new_size, sizeof(*new_vec));
    // copy from old to new
    if (vec->size > 0) memcpy(new_vec, vec->vec, vec->size * sizeof(edge));
    // free the old memory
    if (vec->vec != NULL) free(vec->vec);
    // ues new vec
    vec->max_size = new_size;
    vec->vec = new_vec;
  }
  edge e = {b, w};
  vec->vec[vec->size++] = e;
}

typedef struct heap_node heap_node;
struct heap_node {
  int node;
  long long dist;
  heap_node* left;
  heap_node* right;
};

// join two small heaps
heap_node* join(heap_node* left, heap_node* right) {
  if (left == NULL) return right;
  if (right == NULL) return left;
  if (rand() % 100 < 50) {
    heap_node* z = left;
    left = right;
    right = z;
  }
  if (left->dist < right->dist) {
    left->right = join(left->right, right);
    return left;
  } else {
    right->left = join(left, right->left);
    return right;
  }
}

heap_node* heap_node_new(int node_id, long long dist) {
  heap_node* node = calloc(1, sizeof(heap_node));
  node->node = node_id;
  node->dist = dist;
  node->left = node->right = NULL;
  return node;
}

heap_node* heap_node_pop(heap_node* top) {
  heap_node* left = top->left;
  heap_node* right = top->right;
  free(top);
  return join(left, right);
}

// returns a path from source to destination or NULL if no such path
vector* dijkstra(int n, vector* graph, int source, int destination) {
  // dist[x] = shortest distanct to node x from source
  long long* dist = calloc(n + 1, sizeof(long long));
  int* path_parent = calloc(n + 1, sizeof(int));
  long long inf = 1e18;
  // assuming all nodes are very far away except for source node
  for (int i = 1; i <= n; ++i) dist[i] = inf;
  dist[source] = 0;
  // make an empty heap
  heap_node* heap = NULL;
  // add source node with distance = 0
  heap = join(heap, heap_node_new(source, dist[source]));
  // here we go, looping until we find the destination
  while (heap != NULL) {
    // extract the top heap node
    int u = heap->node;
    long long d = heap->dist;

    // is it the dest node?
    if (u == destination) break;

    // redundant node?
    if (d > dist[u]) continue;

    // pop top node
    heap = heap_node_pop(heap);
    // relax edges
    for (int i = 0; i < graph[u].size; ++i) {
      int v = graph[u].vec[i].to;
      int w = graph[u].vec[i].len;
      // is current path better?
      if (d + w < dist[v]) {
        dist[v] = d + w;
        // to reconstruct the path
        path_parent[v] = u;
        // add it to the heap
        heap = join(heap, heap_node_new(v, dist[v]));
      }
    }
  }

  vector* path = NULL;
  // is there a path?
  if (dist[destination] != inf) {
    path = vector_new();
    // reconstruct the path starting from the destination
    for (int i = destination; i != 0; i = path_parent[i])
      vector_push(path, i, 0);
    // reverse the path
    for (int l = 0, r = path->size - 1; l < r; ++l, --r) {
      // swap, we don't care about the 2nd value, just the first
      int x = path->vec[l].to;
      int y = path->vec[r].to;
      path->vec[l].to = y;
      path->vec[r].to = x;
    }
  }
  // free used memory before returning
  while (heap != NULL) heap = heap_node_pop(heap);
  free(path_parent);
  free(dist);
  return path;
}

int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  // allocate a vector for each node (assuming 1-based indexing)
  vector* graph = calloc(n + 1, sizeof(*graph));
  for (int i = 0; i < m; ++i) {
    int a, b, w;
    scanf("%d%d%d", &a, &b, &w);
    // the graph is undirected, so add two edges, one in each direction
    vector_push(&graph[a], b, w);
    vector_push(&graph[b], a, w);
  }
  // run dijkstra's algorithms
  vector* path = dijkstra(n, graph, 1, n);
  // print path
  if (path == NULL) {
    puts("-1");
  } else {
    for (int i = 0; i < path->size; ++i) printf("%d ", path->vec[i].to);
  }
  free(graph);        // no need
  vector_free(path);  // no need
  return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
  int to;
  int len;
} edge;

typedef struct {
  edge* vec;
  int size;
  int max_size;
} vector;

vector* vector_new() {
  vector* vec = calloc(1, sizeof(*vec));
  return vec;
}

void vector_free(vector* vec) {
  free(vec->vec);
  free(vec);
}

void vector_push(vector* vec, int b, int w) {
  if (vec->size == vec->max_size) {
    // we need to allocate more memory
    int new_size = (vec->size == 0 ? 10 : 2 * vec->size);
    edge* new_vec = calloc(new_size, sizeof(*new_vec));
    // copy from old to new
    if (vec->size > 0) memcpy(new_vec, vec->vec, vec->size * sizeof(edge));
    // free the old memory
    if (vec->vec != NULL) free(vec->vec);
    // ues new vec
    vec->max_size = new_size;
    vec->vec = new_vec;
  }
  edge e = {b, w};
  vec->vec[vec->size++] = e;
}

typedef struct heap_node heap_node;
struct heap_node {
  int node;
  long long dist;
  heap_node* left;
  heap_node* right;
};

// join two small heaps
heap_node* join(heap_node* left, heap_node* right) {
  if (left == NULL) return right;
  if (right == NULL) return left;
  if (rand() % 100 < 50) {
    heap_node* z = left;
    left = right;
    right = z;
  }
  if (left->dist < right->dist) {
    left->right = join(left->right, right);
    return left;
  } else {
    right->left = join(left, right->left);
    return right;
  }
}

heap_node* heap_node_new(int node_id, long long dist) {
  heap_node* node = calloc(1, sizeof(heap_node));
  node->node = node_id;
  node->dist = dist;
  node->left = node->right = NULL;
  return node;
}

heap_node* heap_node_pop(heap_node* top) {
  heap_node* left = top->left;
  heap_node* right = top->right;
  free(top);
  return join(left, right);
}

// returns a path from source to destination or NULL if no such path
vector* dijkstra(int n, vector* graph, int source, int destination) {
  // dist[x] = shortest distanct to node x from source
  long long* dist = calloc(n + 1, sizeof(long long));
  int* path_parent = calloc(n + 1, sizeof(int));
  long long inf = 1e18;
  // assuming all nodes are very far away except for source node
  for (int i = 1; i <= n; ++i) dist[i] = inf;
  dist[source] = 0;
  // make an empty heap
  heap_node* heap = NULL;
  // add source node with distance = 0
  heap = join(heap, heap_node_new(source, dist[source]));
  // here we go, looping until we find the destination
  while (heap != NULL) {
    // extract the top heap node
    int u = heap->node;
    long long d = heap->dist;

    // is it the dest node?
    if (u == destination) break;

    // redundant node?
    if (d > dist[u]) continue;

    // pop top node
    heap = heap_node_pop(heap);
    // relax edges
    for (int i = 0; i < graph[u].size; ++i) {
      int v = graph[u].vec[i].to;
      int w = graph[u].vec[i].len;
      // is current path better?
      if (d + w < dist[v]) {
        dist[v] = d + w;
        // to reconstruct the path
        path_parent[v] = u;
        // add it to the heap
        heap = join(heap, heap_node_new(v, dist[v]));
      }
    }
  }

  vector* path = NULL;
  // is there a path?
  if (dist[destination] != inf) {
    path = vector_new();
    // reconstruct the path starting from the destination
    for (int i = destination; i != 0; i = path_parent[i])
      vector_push(path, i, 0);
    // reverse the path
    for (int l = 0, r = path->size - 1; l < r; ++l, --r) {
      // swap, we don't care about the 2nd value, just the first
      int x = path->vec[l].to;
      int y = path->vec[r].to;
      path->vec[l].to = y;
      path->vec[r].to = x;
    }
  }
  // free used memory before returning
  while (heap != NULL) heap = heap_node_pop(heap);
  free(path_parent);
  free(dist);
  return path;
}

int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  // allocate a vector for each node (assuming 1-based indexing)
  vector* graph = calloc(n + 1, sizeof(*graph));
  for (int i = 0; i < m; ++i) {
    int a, b, w;
    scanf("%d%d%d", &a, &b, &w);
    // the graph is undirected, so add two edges, one in each direction
    vector_push(&graph[a], b, w);
    vector_push(&graph[b], a, w);
  }
  // run dijkstra's algorithms
  vector* path = dijkstra(n, graph, 1, n);
  // print path
  if (path == NULL) {
    puts("-1");
  } else {
    for (int i = 0; i < path->size; ++i) printf("%d ", path->vec[i].to);
    vector_free(path);  // no need
  }
  free(graph);  // no need
  return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
  int to;
  int len;
} edge;

typedef struct {
  edge* vec;
  int size;
  int max_size;
} vector;

vector* vector_new() {
  vector* vec = calloc(1, sizeof(*vec));
  return vec;
}

void vector_free(vector* vec) {
  free(vec->vec);
  vec->vec = NULL;
}

void vector_push(vector* vec, int b, int w) {
  if (vec->size == vec->max_size) {
    // we need to allocate more memory
    int new_size = (vec->size == 0 ? 10 : 2 * vec->size);
    edge* new_vec = calloc(new_size, sizeof(*new_vec));
    // copy from old to new
    if (vec->size > 0) memcpy(new_vec, vec->vec, vec->size * sizeof(edge));
    // free the old memory
    if (vec->vec != NULL) free(vec->vec);
    // ues new vec
    vec->max_size = new_size;
    vec->vec = new_vec;
  }
  edge e = {b, w};
  vec->vec[vec->size++] = e;
}

typedef struct heap_node heap_node;
struct heap_node {
  int node;
  long long dist;
  heap_node* left;
  heap_node* right;
};

// join two small heaps
heap_node* join(heap_node* left, heap_node* right) {
  if (left == NULL) return right;
  if (right == NULL) return left;
  if (left->dist < right->dist) {
    if (rand() & 1) {
      heap_node* lf = left->left;
      heap_node* rg = left->right;
      left->left = rg;
      left->right = lf;
    }
    left->right = join(left->right, right);
    return left;
  } else {
    if (rand() & 1) {
      heap_node* lf = right->left;
      heap_node* rg = right->right;
      right->left = rg;
      right->right = lf;
    }
    right->left = join(left, right->left);
    return right;
  }
}

heap_node* heap_node_new(int node_id, long long dist) {
  heap_node* node = calloc(1, sizeof(heap_node));
  node->node = node_id;
  node->dist = dist;
  node->left = node->right = NULL;
  return node;
}

heap_node* heap_node_pop(heap_node* top) {
  heap_node* left = top->left;
  heap_node* right = top->right;
  free(top);
  top = join(left, right);
  return top;
}

// returns a path from source to destination or NULL if no such path
vector* dijkstra(int n, vector* graph, int source, int destination) {
  // dist[x] = shortest distanct to node x from source
  long long* dist = calloc(n + 1, sizeof(long long));
  int* path_parent = calloc(n + 1, sizeof(int));
  long long inf = 1e18;
  // assuming all nodes are very far away except for source node
  for (int i = 1; i <= n; ++i) dist[i] = inf;
  dist[source] = 0;
  // make an empty heap
  heap_node* heap = NULL;
  // add source node with distance = 0
  heap = join(heap, heap_node_new(source, dist[source]));
  // here we go, looping until we find the destination
  while (heap != NULL) {
    // extract the top heap node
    int u = heap->node;
    long long d = heap->dist;

    // is it the dest node?
    if (u == destination) break;

    // redundant node?
    if (d > dist[u]) continue;

    // pop top node
    heap = heap_node_pop(heap);
    // relax edges
    for (int i = 0; i < graph[u].size; ++i) {
      int v = graph[u].vec[i].to;
      int w = graph[u].vec[i].len;
      // is current path better?
      if (d + w < dist[v]) {
        dist[v] = d + w;
        // to reconstruct the path
        path_parent[v] = u;
        // add it to the heap
        heap = join(heap, heap_node_new(v, dist[v]));
      }
    }
  }

  vector* path = NULL;
  // is there a path?
  if (dist[destination] != inf) {
    path = vector_new();
    // reconstruct the path starting from the destination
    for (int i = destination; i != 0; i = path_parent[i])
      vector_push(path, i, 0);
    // reverse the path
    for (int l = 0, r = path->size - 1; l < r; ++l, --r) {
      // swap, we don't care about the 2nd value, just the first
      int x = path->vec[l].to;
      int y = path->vec[r].to;
      path->vec[l].to = y;
      path->vec[r].to = x;
    }
  }
  // free used memory before returning
  while (heap != NULL) heap = heap_node_pop(heap);
  free(path_parent);
  free(dist);
  return path;
}

int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  // allocate a vector for each node (assuming 1-based indexing)
  vector* graph = calloc(n + 1, sizeof(vector));
  for (int i = 0; i < m; ++i) {
    int a, b, w;
    scanf("%d%d%d", &a, &b, &w);
    // the graph is undirected, so add two edges, one in each direction
    vector_push(&graph[a], b, w);
    vector_push(&graph[b], a, w);
  }
  // run dijkstra's algorithms
  vector* path = dijkstra(n, graph, 1, n);
  // print path
  if (path == NULL) {
    puts("-1");
  } else {
    for (int i = 0; i < path->size; ++i) printf("%d ", path->vec[i].to);
  }
  fflush(stdout);
  free(graph);  // no need
  free(path);   // no need
  return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
  int to;
  int len;
} edge;

typedef struct {
  edge* vec;
  int size;
  int max_size;
} vector;

vector* vector_new() {
  vector* vec = calloc(1, sizeof(vec));
  return vec;
}

void vector_free(vector* vec) {
  free(vec->vec);
  vec->vec = NULL;
}

void vector_push(vector* vec, int b, int w) {
  if (vec->size == vec->max_size) {
    // we need to allocate more memory
    int new_size = (vec->size == 0 ? 10 : 2 * vec->size);
    edge* new_vec = malloc(new_size * sizeof(edge));
    // copy from old to new
    memcpy(vec->vec, new_vec, vec->size * sizeof(int));
    // free the old memory
    free(vec->vec);
    // ues new vec
    vec->max_size = new_size;
    vec->vec = new_vec;
  }
  edge e = {b, w};
  vec->vec[vec->size++] = e;
}

typedef struct heap_node heap_node;
struct heap_node {
  int node;
  long long dist;
  heap_node* left;
  heap_node* right;
};

// join two small heaps
heap_node* join(heap_node* left, heap_node* right) {
  if (left == NULL) return right;
  if (right == NULL) return left;
  if (left->dist < right->dist) {
    left->right = join(left->right, right);
    return left;
  } else {
    right->left = join(left, right->left);
    return right;
  }
}

heap_node* heap_node_new(int node_id, long long dist) {
  heap_node* node = calloc(1, sizeof(heap_node));
  node->node = node_id;
  node->dist = dist;
  return node;
}

heap_node* heap_node_pop(heap_node* top) {
  heap_node* left = top->left;
  heap_node* right = top->right;
  free(top);
  top = join(left, right);
  return top;
}

// returns a path from source to destination or NULL if no such path
vector* dijkstra(int n, vector* graph, int source, int destination) {
  // dist[x] = shortest distanct to node x from source
  long long* dist = calloc(n + 1, sizeof(long long));
  int* path_parent = calloc(n + 1, sizeof(int));
  long long inf = 1e18;
  // assuming all nodes are very far away except for source node
  for (int i = 1; i <= n; ++i) dist[i] = inf;
  dist[source] = 0;
  // make an empty heap
  heap_node* heap = NULL;
  // add source node with distance = 0
  heap = join(heap, heap_node_new(source, dist[source]));
  // here we go, looping until we find the destination
  while (heap != NULL) {
    // extract the top heap node
    int u = heap->node;
    long long d = heap->dist;

    // is it the dest node?
    if (u == destination) break;

    // redundant node?
    if (d > dist[u]) continue;

    // pop top node
    heap = heap_node_pop(heap);
    // relax edges
    for (int i = 0; i < graph[u].size; ++i) {
      int v = graph[u].vec[i].to;
      int w = graph[u].vec[i].len;
      // is current path better?
      if (d + w < dist[v]) {
        dist[v] = d + w;
        // to reconstruct the path
        path_parent[v] = u;
        // add it to the heap
        heap = join(heap, heap_node_new(v, dist[v]));
      }
    }
  }

  vector* path = NULL;
  // is there a path?
  if (dist[destination] != inf) {
    path = vector_new();
    // reconstruct the path starting from the destination
    for (int i = destination; i != 0; i = path_parent[i])
      vector_push(path, i, 0);
    // reverse the path
    for (int l = 0, r = path->size - 1; l < r; ++l, --r) {
      // swap, we don't care about the 2nd value, just the first
      int x = path->vec[l].to;
      int y = path->vec[r].to;
      path->vec[l].to = y;
      path->vec[r].to = x;
    }
  }
  // free used memory before returning
  free(dist);
  free(path_parent);
  while (heap != NULL) heap = heap_node_pop(heap);
  return path;
}

int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  // allocate a vector for each node (assuming 1-based indexing)
  vector* graph = calloc(n + 1, sizeof(vector));
  for (int i = 0; i < m; ++i) {
    int a, b, w;
    scanf("%d%d%d", &a, &b, &w);
    // the graph is undirected, so add two edges, one in each direction
    vector_push(&graph[a], b, w);
    vector_push(&graph[b], a, w);
  }

  // run dijkstra's algorithms
  vector* path = dijkstra(n, graph, 1, n);
  free(graph);  // no need
  // print path
  if (path == NULL) {
    puts("-1");
  } else {
    for (int i = 0; i < path->size; ++i) printf("%d ", path->vec[i].to);
  }
  free(path);  // nod need
  return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
  int to;
  int len;
} edge;

typedef struct {
  edge* vec;
  int size;
  int max_size;
} vector;

vector* vector_new() {
  vector* vec = calloc(1, sizeof(*vec));
  return vec;
}

void vector_free(vector* vec) {
  free(vec->vec);
  vec->vec = NULL;
}

void vector_push(vector* vec, int b, int w) {
  if (vec->size == vec->max_size) {
    // we need to allocate more memory
    int new_size = (vec->size == 0 ? 10 : 2 * vec->size);
    edge* new_vec = calloc(new_size, sizeof(*new_vec));
    // copy from old to new
    if (vec->size > 0) memcpy(new_vec, vec->vec, vec->size * sizeof(edge));
    // free the old memory
    if (vec->vec != NULL) free(vec->vec);
    // ues new vec
    vec->max_size = new_size;
    vec->vec = new_vec;
  }
  edge e = {b, w};
  vec->vec[vec->size++] = e;
}

typedef struct heap_node heap_node;
struct heap_node {
  int node;
  long long dist;
  heap_node* left;
  heap_node* right;
};

// join two small heaps
heap_node* join(heap_node* left, heap_node* right) {
  if (left == NULL) return right;
  if (right == NULL) return left;
  if (left->dist < right->dist) {
    left->right = join(left->right, right);
    return left;
  } else {
    right->left = join(left, right->left);
    return right;
  }
}

heap_node* heap_node_new(int node_id, long long dist) {
  heap_node* node = calloc(1, sizeof(heap_node));
  node->node = node_id;
  node->dist = dist;
  node->left = node->right = NULL;
  return node;
}

heap_node* heap_node_pop(heap_node* top) {
  heap_node* left = top->left;
  heap_node* right = top->right;
  free(top);
  top = join(left, right);
  return top;
}

// returns a path from source to destination or NULL if no such path
vector* dijkstra(int n, vector* graph, int source, int destination) {
  // dist[x] = shortest distanct to node x from source
  long long* dist = calloc(n + 1, sizeof(long long));
  int* path_parent = calloc(n + 1, sizeof(int));
  long long inf = 1e18;
  // assuming all nodes are very far away except for source node
  for (int i = 1; i <= n; ++i) dist[i] = inf;
  dist[source] = 0;
  // make an empty heap
  heap_node* heap = NULL;
  // add source node with distance = 0
  heap = join(heap, heap_node_new(source, dist[source]));
  // here we go, looping until we find the destination
  while (heap != NULL) {
    // extract the top heap node
    int u = heap->node;
    long long d = heap->dist;

    // is it the dest node?
    if (u == destination) break;

    // redundant node?
    if (d > dist[u]) continue;

    // pop top node
    heap = heap_node_pop(heap);
    // relax edges
    for (int i = 0; i < graph[u].size; ++i) {
      int v = graph[u].vec[i].to;
      int w = graph[u].vec[i].len;
      // is current path better?
      if (d + w < dist[v]) {
        dist[v] = d + w;
        // to reconstruct the path
        path_parent[v] = u;
        // add it to the heap
        heap = join(heap, heap_node_new(v, dist[v]));
      }
    }
  }

  vector* path = NULL;
  // is there a path?
  if (dist[destination] != inf) {
    path = vector_new();
    // reconstruct the path starting from the destination
    for (int i = destination; i != 0; i = path_parent[i])
      vector_push(path, i, 0);
    // reverse the path
    for (int l = 0, r = path->size - 1; l < r; ++l, --r) {
      // swap, we don't care about the 2nd value, just the first
      int x = path->vec[l].to;
      int y = path->vec[r].to;
      path->vec[l].to = y;
      path->vec[r].to = x;
    }
  }
  // free used memory before returning
  while (heap != NULL) heap = heap_node_pop(heap);
  free(path_parent);
  free(dist);
  return path;
}

int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  // allocate a vector for each node (assuming 1-based indexing)
  vector* graph = calloc(n + 1, sizeof(vector));
  for (int i = 0; i < m; ++i) {
    int a, b, w;
    scanf("%d%d%d", &a, &b, &w);
    // the graph is undirected, so add two edges, one in each direction
    vector_push(&graph[a], b, w);
    vector_push(&graph[b], a, w);
  }
  // run dijkstra's algorithms
  vector* path = dijkstra(n, graph, 1, n);
  // print path
  if (path == NULL) {
    puts("-1");
  } else {
    for (int i = 0; i < path->size; ++i) printf("%d ", path->vec[i].to);
  }
  fflush(stdout);
  free(graph);  // no need
  free(path);   // no need
  return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
  int to;
  int len;
} edge;

typedef struct {
  edge* vec;
  int size;
  int max_size;
} vector;

vector* vector_new() {
  vector* vec = calloc(1, sizeof(*vec));
  return vec;
}

void vector_free(vector* vec) {
  free(vec->vec);
  free(vec);
}

void vector_push(vector* vec, int b, int w) {
  if (vec->size == vec->max_size) {
    // we need to allocate more memory
    int new_size = (vec->size == 0 ? 10 : 2 * vec->size);
    edge* new_vec = calloc(new_size, sizeof(*new_vec));
    // copy from old to new
    if (vec->size > 0) memcpy(new_vec, vec->vec, vec->size * sizeof(edge));
    // free the old memory
    if (vec->vec != NULL) free(vec->vec);
    // ues new vec
    vec->max_size = new_size;
    vec->vec = new_vec;
  }
  edge e = {b, w};
  vec->vec[vec->size++] = e;
}

typedef struct heap_node heap_node;
struct heap_node {
  int node;
  long long dist;
  heap_node* left;
  heap_node* right;
};

// join two small heaps
heap_node* join(heap_node* left, heap_node* right) {
  if (left == NULL) return right;
  if (right == NULL) return left;
  if (rand() % 100 < 50) {
    heap_node* z = left;
    left = right;
    right = z;
  }
  if (left->dist < right->dist) {
    left->right = join(left->right, right);
    return left;
  } else {
    right->left = join(left, right->left);
    return right;
  }
}

heap_node* heap_node_new(int node_id, long long dist) {
  heap_node* node = calloc(1, sizeof(heap_node));
  node->node = node_id;
  node->dist = dist;
  node->left = node->right = NULL;
  return node;
}

heap_node* heap_node_pop(heap_node* top) {
  heap_node* left = top->left;
  heap_node* right = top->right;
  free(top);
  return join(left, right);
}

// returns a path from source to destination or NULL if no such path
vector* dijkstra(int n, vector* graph, int source, int destination) {
  // dist[x] = shortest distanct to node x from source
  long long* dist = calloc(n + 1, sizeof(long long));
  int* path_parent = calloc(n + 1, sizeof(int));
  long long inf = 1e18;
  // assuming all nodes are very far away except for source node
  for (int i = 1; i <= n; ++i) dist[i] = inf;
  dist[source] = 0;
  // make an empty heap
  heap_node* heap = NULL;
  // add source node with distance = 0
  heap = join(heap, heap_node_new(source, dist[source]));
  // here we go, looping until we find the destination
  while (heap != NULL) {
    // extract the top heap node
    int u = heap->node;
    long long d = heap->dist;

    // pop top node
    heap = heap_node_pop(heap);

    // is it the dest node?
    if (u == destination) break;

    // redundant node?
    if (d > dist[u]) continue;

    // relax edges
    for (int i = 0; i < graph[u].size; ++i) {
      int v = graph[u].vec[i].to;
      int w = graph[u].vec[i].len;
      // is current path better?
      if (d + w < dist[v]) {
        dist[v] = d + w;
        // to reconstruct the path
        path_parent[v] = u;
        // add it to the heap
        heap = join(heap, heap_node_new(v, dist[v]));
      }
    }
  }

  vector* path = NULL;
  // is there a path?
  if (dist[destination] != inf) {
    path = vector_new();
    // reconstruct the path starting from the destination
    for (int i = destination; i != 0; i = path_parent[i])
      vector_push(path, i, 0);
    // reverse the path
    for (int l = 0, r = path->size - 1; l < r; ++l, --r) {
      // swap, we don't care about the 2nd value, just the first
      int x = path->vec[l].to;
      int y = path->vec[r].to;
      path->vec[l].to = y;
      path->vec[r].to = x;
    }
  }
  // free used memory before returning
  while (heap != NULL) heap = heap_node_pop(heap);
  free(path_parent);
  free(dist);
  return path;
}

int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  // allocate a vector for each node (assuming 1-based indexing)
  vector* graph = calloc(n + 1, sizeof(*graph));
  for (int i = 0; i < m; ++i) {
    int a, b, w;
    scanf("%d%d%d", &a, &b, &w);
    // the graph is undirected, so add two edges, one in each direction
    vector_push(&graph[a], b, w);
    vector_push(&graph[b], a, w);
  }
  // run dijkstra's algorithms
  vector* path = dijkstra(n, graph, 1, n);
  // print path
  if (path == NULL) {
    puts("-1");
  } else {
    for (int i = 0; i < path->size; ++i) printf("%d ", path->vec[i].to);
    vector_free(path);  // no need
  }
  free(graph);  // no need
  return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
  int to;
  int len;
} edge;

typedef struct {
  edge* vec;
  int size;
  int max_size;
} vector;

vector* vector_new() {
  vector* vec = calloc(1, sizeof(vec));
  return vec;
}

void vector_free(vector* vec) {
  free(vec->vec);
  vec->vec = NULL;
}

void vector_push(vector* vec, int b, int w) {
  if (vec->size == vec->max_size) {
    // we need to allocate more memory
    int new_size = (vec->size == 0 ? 10 : 2 * vec->size);
    edge* new_vec = calloc(new_size, sizeof(edge));
    // copy from old to new
    if (vec->size > 0) memcpy(vec->vec, new_vec, vec->size * sizeof(int));
    // free the old memory
    if (vec->vec != NULL) free(vec->vec);
    // ues new vec
    vec->max_size = new_size;
    vec->vec = new_vec;
  }
  edge e = {b, w};
  vec->vec[vec->size++] = e;
}

typedef struct heap_node heap_node;
struct heap_node {
  int node;
  long long dist;
  heap_node* left;
  heap_node* right;
};

// join two small heaps
heap_node* join(heap_node* left, heap_node* right) {
  if (left == NULL) return right;
  if (right == NULL) return left;
  if (left->dist < right->dist) {
    left->right = join(left->right, right);
    return left;
  } else {
    right->left = join(left, right->left);
    return right;
  }
}

heap_node* heap_node_new(int node_id, long long dist) {
  heap_node* node = calloc(1, sizeof(heap_node));
  node->node = node_id;
  node->dist = dist;
  node->left = node->right = NULL;
  return node;
}

heap_node* heap_node_pop(heap_node* top) {
  heap_node* left = top->left;
  heap_node* right = top->right;
  free(top);
  top = join(left, right);
  return top;
}

// returns a path from source to destination or NULL if no such path
vector* dijkstra(int n, vector* graph, int source, int destination) {
  // dist[x] = shortest distanct to node x from source
  long long* dist = calloc(n + 1, sizeof(long long));
  int* path_parent = calloc(n + 1, sizeof(int));
  long long inf = 1e18;
  // assuming all nodes are very far away except for source node
  for (int i = 1; i <= n; ++i) dist[i] = inf;
  dist[source] = 0;
  // make an empty heap
  heap_node* heap = NULL;
  // add source node with distance = 0
  heap = join(heap, heap_node_new(source, dist[source]));
  // here we go, looping until we find the destination
  while (heap != NULL) {
    // extract the top heap node
    int u = heap->node;
    long long d = heap->dist;

    // is it the dest node?
    if (u == destination) break;

    // redundant node?
    if (d > dist[u]) continue;

    // pop top node
    heap = heap_node_pop(heap);
    // relax edges
    for (int i = 0; i < graph[u].size; ++i) {
      int v = graph[u].vec[i].to;
      int w = graph[u].vec[i].len;
      // is current path better?
      if (d + w < dist[v]) {
        dist[v] = d + w;
        // to reconstruct the path
        path_parent[v] = u;
        // add it to the heap
        heap = join(heap, heap_node_new(v, dist[v]));
      }
    }
  }

  vector* path = NULL;
  // is there a path?
  if (dist[destination] != inf) {
    path = vector_new();
    // reconstruct the path starting from the destination
    for (int i = destination; i != 0; i = path_parent[i])
      vector_push(path, i, 0);
    // reverse the path
    for (int l = 0, r = path->size - 1; l < r; ++l, --r) {
      // swap, we don't care about the 2nd value, just the first
      int x = path->vec[l].to;
      int y = path->vec[r].to;
      path->vec[l].to = y;
      path->vec[r].to = x;
    }
  }
  // free used memory before returning
  free(dist);
  free(path_parent);
  while (heap != NULL) heap = heap_node_pop(heap);
  return path;
}

int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  // allocate a vector for each node (assuming 1-based indexing)
  vector* graph = calloc(n + 1, sizeof(vector));
  for (int i = 0; i < m; ++i) {
    int a, b, w;
    scanf("%d%d%d", &a, &b, &w);
    // the graph is undirected, so add two edges, one in each direction
    vector_push(&graph[a], b, w);
    vector_push(&graph[b], a, w);
  }
  // run dijkstra's algorithms
  vector* path = dijkstra(n, graph, 1, n);
  free(graph);  // no need
  // print path
  if (path == NULL) {
    puts("-1");
  } else {
    for (int i = 0; i < path->size; ++i) printf("%d ", path->vec[i].to);
  }
  free(path);  // no need
  return 0;
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef long long ll;
typedef struct {ll v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
bool vis[N];
list *g[N];
ll n, m, a, b, w, size, dist[N], ans[N], ind;
pair pq[N];
void min_heapify(ll ind){
    ll l=ind*2, r=l+1, lowest=ind;
    if (l<=size&&(pq[l].v<pq[ind].v||pq[l].w<pq[ind].w))
        lowest=l;
    if (r<=size&&(pq[r].v<pq[ind].v||pq[r].w<pq[ind].w))
        lowest=r;
    if (lowest!=ind){
        pair tmp=pq[ind];
        pq[ind]=pq[lowest];
        pq[lowest]=tmp;
        min_heapify(lowest);
    }
}
void build_min_heap(void){
    for (ll i=size/2; i; i--)
        min_heapify(i);
}
pair extract_min(void){
    pair min=pq[1];
    pq[1]=pq[size];
    size--;
    min_heapify(1);
    return min;
}
void pushh(ll v, ll w){
    ++size;
    pq[size].v=v;
    pq[size].w=w;
    min_heapify(size);
}
void pushg(ll u, ll v, ll w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
void dfs(ll v){
	vis[v]=1;
	for (list *a=g[v]; a; a=a->next)
		if (!vis[a->p.v]){
			ans[ind]=a->p.v;
			ind++;
			dfs(a->p.v);
		}
}
int main(){
    scanf("%I64d%I64d", &n, &m);
    for (ll i=1; i<=n; i++)
    	dist[i]=LLONG_MAX;
    while (m--){
        scanf("%I64d%I64d%I64d", &a, &b, &w);
        pushg(a, b, w);
        pushg(b, a, w);
    }
    pushh(1, 0);
    while (size){
        pair p=extract_min();
        ll d=p.w, u=p.v;
        if (d>dist[u])
            continue;
        for (list *a=g[u]; a; a=a->next){
            pair v=a->p;
            if (dist[u]+v.w<dist[v.v]){
                dist[v.v]=dist[u]+v.w;
                pushh(v.v, v.w);
            }
        }
    }
    dfs(1);
    if (!vis[n]){
    	printf("-1");
    	return 0;
    }
    printf("1 ");
    for (ll i=0; ans[i]!=n; i++)
    	printf("%I64d ", ans[i]);
    printf("%I64d", n);
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef long long ll;
typedef struct {ll v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
list *g[N];
ll n, m, u, v, w, size, dist[N], prev[N];
pair pq[N];
pair top(void){
    pair min=pq[1];
    pq[1]=pq[size];
    size--;
    return min;
}
void pushh(ll v, ll w){
    ++size;
    pq[size].v=v;
    pq[size].w=w;
}
void pushg(ll u, ll v, ll w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
void dijkstra(ll s){
    for (ll i=1; i<=n; i++)
        dist[i]=LLONG_MAX;
    dist[s]=0;
    pushh(1, 0);
    while (size){
        pair p=top();
        ll u=p.v;
        for (list *a=g[u]; a; a=a->next){
            pair v=a->p;
            if (dist[u]+v.w<dist[v.v]){
                dist[v.v]=dist[u]+v.w;
                prev[v.v]=u;
                pushh(v.v, w);
            }
        }
    }
}
void output(ll v){
    if (prev[v])
        output(prev[v]);
    printf("%lld ", v);
}
int main(){
    scanf("%lld%lld", &n, &m);
    while (m--){
        scanf("%lld%lld%lld", &u, &v, &w);
        pushg(u, v, w);
        pushg(v, u, w);
    }
    dijkstra(1);
    prev[1]=0;
    if (prev[n])
        output(n);
    else
        printf("-1");
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef long long ll;
typedef struct {ll v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
list *g[N];
ll n, m, u, v, w, size, dist[N], prev[N];
pair pq[N];
void min_heapify(ll ind){
    ll l=ind*2, r=l+1, lowest=ind;
    if (l<=size&&(pq[l].v<pq[ind].v||pq[l].w<pq[ind].w))
        lowest=l;
    if (r<=size&&(pq[r].v<pq[ind].v||pq[r].w<pq[ind].w))
        lowest=r;
    if (lowest!=ind){
        pair tmp=pq[ind];
        pq[ind]=pq[lowest];
        pq[lowest]=tmp;
        min_heapify(lowest);
    }
}
pair top(void){
    pair min=pq[1];
    pq[1]=pq[size];
    size--;
    min_heapify(1);
    return min;
}
void pushh(ll v, ll w){
    ++size;
    pq[size].v=v;
    pq[size].w=w;
    min_heapify(size/2);
}
void pushg(ll u, ll v, ll w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
void dijkstra(ll s){
    for (ll i=1; i<=n; i++)
        dist[i]=LLONG_MAX;
    dist[s]=0;
    pushh(1, 0);
    while (size){
        pair p=top();
        ll u=p.v;
        for (list *a=g[u]; a; a=a->next){
            pair v=a->p;
            if (dist[u]+v.w<dist[v.v]){
                dist[v.v]=dist[u]+v.w;
                prev[v.v]=u;
                pushh(v.v, w);
            }
        }
    }
}
void output(ll v){
    if (prev[v])
        output(prev[v]);
    printf("%lld ", v);
}
int main(){
    scanf("%lld%lld", &n, &m);
    while (m--){
        scanf("%lld%lld%lld", &u, &v, &w);
        pushg(u, v, w);
        pushg(v, u, w);
    }
    dijkstra(1);
    prev[1]=0;
    if (prev[n])
        output(n);
    else
        printf("-1");
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef long long ll;
typedef struct {ll v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
list *g[N];
ll n, m, a, b, w, size, dist[N], prev[N], ans[N], ind;
pair pq[N];
void min_heapify(ll ind){
    ll l=ind*2, r=l+1, lowest=ind;
    if (l<=size&&(pq[l].v<pq[ind].v||pq[l].w<pq[ind].w))
        lowest=l;
    if (r<=size&&(pq[r].v<pq[ind].v||pq[r].w<pq[ind].w))
        lowest=r;
    if (lowest!=ind){
        pair tmp=pq[ind];
        pq[ind]=pq[lowest];
        pq[lowest]=tmp;
        min_heapify(lowest);
    }
}
pair extract_min(void){
    pair min=pq[1];
    pq[1]=pq[size];
    size--;
    min_heapify(1);
    return min;
}
void pushh(ll v, ll w){
    ++size;
    pq[size].v=v;
    pq[size].w=w;
    min_heapify(size);
}
void pushg(ll u, ll v, ll w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
int main(){
    scanf("%I64d%I64d", &n, &m);
    for (ll i=1; i<=n; i++)
        dist[i]=LLONG_MAX;
    while (m--){
        scanf("%I64d%I64d%I64d", &a, &b, &w);
        pushg(a, b, w);
        pushg(b, a, w);
    }
    pushh(1, 0);
    while (size){
        pair p=extract_min();
        for (list *a=g[p.v]; a; a=a->next){
            pair v=a->p;
            if (dist[p.v]+v.w<dist[v.v]){
                dist[v.v]=dist[p.v]+v.w;
                prev[v.v]=p.v;
                pushh(v.v, v.w);
            }
        }
    }
    if (!prev[n]){
    	printf("-1");
    	return 0;
    }
    prev[1]=0;
    a=n;
    if (prev[a])
    	while (prev[a]){
    		ans[ind]=a;
    		a=prev[a];
    		ind++;
    	}
    printf("1 ");
    for (ll i=ind-1; i>=0; i--)
    	printf("%I64d ", ans[i]);
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef long long ll;
typedef struct {ll v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
list *g[N];
ll n, m, a, b, w, size, dist[N], prev[N], ans[N], ind;
pair pq[N];
void min_heapify(ll ind){
    ll l=ind*2, r=l+1, lowest=ind;
    if (l<=size&&(pq[l].v<pq[ind].v||pq[l].w<pq[ind].w))
        lowest=l;
    if (r<=size&&(pq[r].v<pq[ind].v||pq[r].w<pq[ind].w))
        lowest=r;
    if (lowest!=ind){
        pair tmp=pq[ind];
        pq[ind]=pq[lowest];
        pq[lowest]=tmp;
        min_heapify(lowest);
    }
}
pair extract_min(void){
    pair min=pq[1];
    pq[1]=pq[size];
    size--;
    min_heapify(1);
    return min;
}
void pushh(ll v, ll w){
    ++size;
    pq[size].v=v;
    pq[size].w=w;
    min_heapify(size);
}
void pushg(ll u, ll v, ll w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
int main(){
    scanf("%I64d%I64d", &n, &m);
    for (ll i=1; i<=n; i++)
        dist[i]=LLONG_MAX;
    while (m--){
        scanf("%I64d%I64d%I64d", &a, &b, &w);
        pushg(a, b, w);
        pushg(b, a, w);
    }
    pushh(1, 0);
    while (size){
        pair p=extract_min();
        ll /*d=p.w,*/ u=p.v;
        //if (d>dist[u])
            //continue;
        for (list *a=g[u]; a; a=a->next){
            pair v=a->p;
            if (dist[u]+v.w<dist[v.v]){
                dist[v.v]=dist[u]+v.w;
                prev[v.v]=u;
                pushh(v.v, v.w);
            }
        }
    }
    if (!prev[n]){
    	printf("-1");
    	return 0;
    }
    prev[1]=0;
    a=n;
    if (prev[a])
    	while (prev[a]){
    		ans[ind]=a;
    		a=prev[a];
    		ind++;
    	}
    printf("1 ");
    for (ll i=ind-1; i>=0; i--)
    	printf("%I64d ", ans[i]);
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef long long ll;
typedef struct {ll v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
list *g[N];
ll n, m, a, b, w, size, dist[N], prev[N];
pair pq[N];
pair extract_top(void){
    pair min=pq[1];
    pq[1]=pq[size];
    size--;
    return min;
}
void pushh(ll v, ll w){
    ++size;
    pq[size].v=v;
    pq[size].w=w;
}
void pushg(ll u, ll v, ll w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
void dijkstra(void){
    for (ll i=1; i<=n; i++)
        dist[i]=LLONG_MAX;
    pushh(1, 0);
    while (size){
        pair p=extract_top();
        ll u=p.v;
        for (list *a=g[u]; a; a=a->next){
            pair v=a->p;
            if (dist[u]+v.w<dist[v.v]){
                dist[v.v]=dist[u]+v.w;
                prev[v.v]=u;
                pushh(v.v, v.w);
            }
        }
    }
}
void output(ll v){
	if (prev[v])
		output(prev[v]);
	printf("%lld ", v);
}
int main(){
    scanf("%I64d%I64d", &n, &m);
    while (m--){
        scanf("%I64d%I64d%I64d", &a, &b, &w);
        pushg(a, b, w);
        pushg(b, a, w);
    }
    dijkstra();
    if (!prev[n]){
    	printf("-1");
    	return 0;
    }
    prev[1]=0;
    output(n);
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef long long ll;
typedef struct {ll v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
list *g[N];
ll n, m, u, v, w, size, dist[N], prev[N];
pair pq[N];
void min_heapify(ll ind){
	if (!ind)
		return;
    ll l=ind*2, r=l+1, lowest=ind;
    if (l<=size&&(pq[l].v<pq[ind].v||pq[l].w<pq[ind].w))
        lowest=l;
    if (r<=size&&(pq[r].v<pq[ind].v||pq[r].w<pq[ind].w))
        lowest=r;
    if (lowest!=ind){
        pair tmp=pq[ind];
        pq[ind]=pq[lowest];
        pq[lowest]=tmp;
        min_heapify(lowest);
    }
}
pair top(void){
    pair min=pq[1];
    pq[1]=pq[size];
    size--;
    min_heapify(1);
    return min;
}
void pushh(ll v, ll w){
    ++size;
    pq[size].v=v;
    pq[size].w=w;
    min_heapify(size/2);
}
void pushg(ll u, ll v, ll w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
void dijkstra(ll s){
    for (ll i=1; i<=n; i++)
        dist[i]=LLONG_MAX;
    dist[s]=0;
    pushh(1, 0);
    while (size){
        pair p=top();
        ll u=p.v;
        for (list *a=g[u]; a; a=a->next){
            pair v=a->p;
            if (dist[u]+v.w<dist[v.v]){
                dist[v.v]=dist[u]+v.w;
                prev[v.v]=u;
                pushh(v.v, w);
            }
        }
    }
}
void output(ll v){
    if (prev[v])
        output(prev[v]);
    printf("%lld ", v);
}
int main(){
    scanf("%lld%lld", &n, &m);
    while (m--){
        scanf("%lld%lld%lld", &u, &v, &w);
        pushg(u, v, w);
        pushg(v, u, w);
    }
    dijkstra(1);
    prev[1]=0;
    if (prev[n])
        output(n);
    else
        printf("-1");
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef long long ll;
typedef struct {ll v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
list *g[N];
ll n, m, a, b, w, size, dist[N], prev[N];
pair pq[N];
void min_heapify(ll ind){
    ll l=ind*2, r=l+1, lowest=ind;
    if (l<=size&&(pq[l].v<pq[ind].v||pq[l].w<pq[ind].w))
        lowest=l;
    if (r<=size&&(pq[r].v<pq[ind].v||pq[r].w<pq[ind].w))
        lowest=r;
    if (lowest!=ind){
        pair tmp=pq[ind];
        pq[ind]=pq[lowest];
        pq[lowest]=tmp;
        min_heapify(lowest);
    }
}
pair extract_min(void){
    pair min=pq[1];
    pq[1]=pq[size];
    size--;
    min_heapify(1);
    return min;
}
void pushh(ll v, ll w){
    ++size;
    pq[size].v=v;
    pq[size].w=w;
    min_heapify(size);
}
void pushg(ll u, ll v, ll w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
void dijkstra(void){
    for (ll i=1; i<=n; i++)
        dist[i]=LLONG_MAX;
    pushh(1, 0);
    while (size){
        pair p=extract_min();
        ll u=p.v;
        for (list *a=g[u]; a; a=a->next){
            pair v=a->p;
            if (dist[u]+v.w<dist[v.v]){
                dist[v.v]=dist[u]+v.w;
                prev[v.v]=u;
                pushh(v.v, v.w);
            }
        }
    }
}
void output(ll v){
	if (prev[v])
		output(prev[v]);
	printf("%lld ", v);
}
int main(){
    scanf("%I64d%I64d", &n, &m);
    while (m--){
        scanf("%I64d%I64d%I64d", &a, &b, &w);
        pushg(a, b, w);
        pushg(b, a, w);
    }
    dijkstra();
    if (!prev[n]){
    	printf("-1");
    	return 0;
    }
    prev[1]=0;
    output(n);
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef long long ll;
typedef struct {ll v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
list *g[N];
ll n, m, a, b, w, size, dist[N], prev[N], ans[N], ind;
pair pq[N];
void min_heapify(ll ind){
    ll l=ind*2, r=l+1, lowest=ind;
    if (l<=size&&(pq[l].v<pq[ind].v||pq[l].w<pq[ind].w))
        lowest=l;
    if (r<=size&&(pq[r].v<pq[ind].v||pq[r].w<pq[ind].w))
        lowest=r;
    if (lowest!=ind){
        pair tmp=pq[ind];
        pq[ind]=pq[lowest];
        pq[lowest]=tmp;
        min_heapify(lowest);
    }
}
void build_min_heap(void){
    for (ll i=size/2; i; i--)
        min_heapify(i);
}
pair extract_min(void){
    pair min=pq[1];
    pq[1]=pq[size];
    size--;
    min_heapify(1);
    return min;
}
void pushh(ll v, ll w){
    ++size;
    pq[size].v=v;
    pq[size].w=w;
    min_heapify(size);
}
void pushg(ll u, ll v, ll w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
void dijkstra(void){
    for (ll i=1; i<=n; i++)
        dist[i]=LLONG_MAX;
    pushh(1, 0);
    while (size){
        pair p=extract_min();
        ll u=p.v;
        for (list *a=g[u]; a; a=a->next){
            pair v=a->p;
            if (dist[u]+v.w<dist[v.v]){
                dist[v.v]=dist[u]+v.w;
                prev[v.v]=u;
                pushh(v.v, v.w);
            }
        }
    }
}
int main(){
    scanf("%I64d%I64d", &n, &m);
    while (m--){
        scanf("%I64d%I64d%I64d", &a, &b, &w);
        pushg(a, b, w);
        pushg(b, a, w);
    }
    dijkstra();

    if (!prev[n]){
    	printf("-1");
    	return 0;
    }
    prev[1]=0;
    a=n;
    if (prev[a])
    	while (prev[a]){
    		ans[ind]=a;
    		a=prev[a];
    		ind++;
    	}
    printf("1 ");
    for (ll i=ind-1; i>=0; i--)
    	printf("%I64d ", ans[i]);
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef long long ll;
typedef struct {ll v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
list *g[N];
ll n, m, a, b, w, size, dist[N], prev[N];
pair pq[N];
void min_heapify(ll ind){
    ll l=ind*2, r=l+1, lowest=ind;
    if (l<=size&&(pq[l].v<pq[ind].v||pq[l].w<pq[ind].w))
        lowest=l;
    if (r<=size&&(pq[r].v<pq[ind].v||pq[r].w<pq[ind].w))
        lowest=r;
    if (lowest!=ind){
        pair tmp=pq[ind];
        pq[ind]=pq[lowest];
        pq[lowest]=tmp;
        min_heapify(lowest);
    }
}
void build_min_heap(void){
    for (ll i=size/2; i; i--)
        min_heapify(i);
}
pair extract_min(void){
    pair min=pq[1];
    pq[1]=pq[size];
    size--;
    min_heapify(1);
    return min;
}
void pushh(ll v, ll w){
    ++size;
    pq[size].v=v;
    pq[size].w=w;
    build_min_heap();
}
void pushg(ll u, ll v, ll w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
void dijkstra(void){
    for (ll i=1; i<=n; i++)
        dist[i]=LLONG_MAX;
    pushh(1, 0);
    while (size){
        pair p=extract_min();
        ll u=p.v;
        for (list *a=g[u]; a; a=a->next){
            pair v=a->p;
            if (dist[u]+v.w<dist[v.v]){
                dist[v.v]=dist[u]+v.w;
                prev[v.v]=u;
                pushh(v.v, v.w);
            }
        }
    }
}
void output(ll v){
	if (prev[v])
		output(prev[v]);
	printf("%lld ", v);
}
int main(){
    scanf("%I64d%I64d", &n, &m);
    while (m--){
        scanf("%I64d%I64d%I64d", &a, &b, &w);
        pushg(a, b, w);
        pushg(b, a, w);
    }
    dijkstra();
    if (!prev[n]){
    	printf("-1");
    	return 0;
    }
    prev[1]=0;
    output(n);
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef struct {int v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
list *g[N];
int n, m, u, v, w, dist[N], prev[N];
void pushg(int u, int v, int w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
void init(void){
    for (int i=1; i<=n; i++)
        dist[i]=INT_MAX;
}
void BFrelax(void){
    init();
    for (int i=1; i<n; i++)
        for (int j=1; j<=n; j++)
            for (list *a=g[j]; a; a=a->next){
                u=j; v=a->p.v; w=a->p.w;
                if (dist[u]+w<dist[v]){
                    dist[v]=dist[u]+w;
                    prev[v]=u;
                }
            }
}
void output(int v){
    if (prev[v])
        output(prev[v]);
    printf("%d ", v);
}
int main(){
    scanf("%d%d", &n, &m);
    while (m--){
        scanf("%d%d%d", &u, &v, &w);
        pushg(u, v, w);
        pushg(v, u, w);
    }
    BFrelax();
    prev[1]=0;
    if (prev[n])
        output(n);
    else
        printf("-1");
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef long long ll;
typedef struct {ll v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
list *g[N];
ll n, m, u, v, w, size, dist[N], prev[N];
pair pq[N];
void min_heapify(ll ind){
    ll l=ind*2, r=l+1, lowest=ind;
    if (l<=size&&(pq[l].v<pq[ind].v||pq[l].w<pq[ind].w))
        lowest=l;
    if (r<=size&&(pq[r].v<pq[ind].v||pq[r].w<pq[ind].w))
        lowest=r;
    if (lowest!=ind){
        pair tmp=pq[ind];
        pq[ind]=pq[lowest];
        pq[lowest]=tmp;
        min_heapify(lowest);
    }
}
pair top(void){
    pair min=pq[1];
    pq[1]=pq[size];
    size--;
    min_heapify(1);
    return min;
}
void pushh(ll v, ll w){
    ++size;
    pq[size].v=v;
    pq[size].w=w;
}
void pushg(ll u, ll v, ll w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
void dijkstra(ll s){
    for (ll i=1; i<=n; i++)
        dist[i]=LLONG_MAX;
    dist[s]=0;
    pushh(1, 0);
    while (size){
        pair p=top();
        ll u=p.v;
        for (list *a=g[u]; a; a=a->next){
            pair v=a->p;
            if (dist[u]+v.w<dist[v.v]){
                dist[v.v]=dist[u]+v.w;
                prev[v.v]=u;
                pushh(v.v, w);
            }
        }
    }
}
void output(ll v){
    if (prev[v])
        output(prev[v]);
    printf("%lld ", v);
}
int main(){
    scanf("%lld%lld", &n, &m);
    while (m--){
        scanf("%lld%lld%lld", &u, &v, &w);
        pushg(u, v, w);
        pushg(v, u, w);
    }
    dijkstra(1);
    prev[1]=0;
    if (prev[n])
        output(n);
    else
        printf("-1");
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef long long ll;
typedef struct {ll v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
list *g[N];
ll n, m, u, v, w, dist[N], prev[N];
void pushg(ll u, ll v, ll w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
void init(void){
    for (ll i=1; i<=n; i++)
        dist[i]=LLONG_MAX;
}
void BFrelax(void){
    init();
    for (ll i=1; i<n; i++)
        for (ll j=1; j<=n; j++)
            for (list *a=g[j]; a; a=a->next){
                u=j; v=a->p.v; w=a->p.w;
                if (dist[u]+w<dist[v]){
                    dist[v]=dist[u]+w;
                    prev[v]=u;
                }
            }
}
void output(ll v){
    if (prev[v])
        output(prev[v]);
    printf("%lld ", v);
}
int main(){
    scanf("%lld%lld", &n, &m);
    while (m--){
        scanf("%lld%lld%lld", &u, &v, &w);
        pushg(u, v, w);
        pushg(v, u, w);
    }
    BFrelax();
    prev[1]=0;
    if (prev[n])
        output(n);
    else
        printf("-1");
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef long long ll;
typedef struct {ll v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
list *g[N];
ll n, m, a, b, w, size, dist[N], prev[N];
pair pq[N];
void min_heapify(ll ind){
    ll l=ind*2, r=l+1, lowest=ind;
    if (l<=size&&(pq[l].v<pq[ind].v||pq[l].w<pq[ind].w))
        lowest=l;
    if (r<=size&&(pq[r].v<pq[ind].v||pq[r].w<pq[ind].w))
        lowest=r;
    if (lowest!=ind){
        pair tmp=pq[ind];
        pq[ind]=pq[lowest];
        pq[lowest]=tmp;
        min_heapify(lowest);
    }
}
void build_min_heap(void){
    for (ll i=size/2; i; i--)
        min_heapify(i);
}
pair extract_min(void){
    pair min=pq[1];
    pq[1]=pq[size];
    size--;
    min_heapify(1);
    return min;
}
void pushh(ll v, ll w){
    ++size;
    pq[size].v=v;
    pq[size].w=w;
    min_heapify(size);
}
void pushg(ll u, ll v, ll w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
void dijkstra(void){
    for (ll i=1; i<=n; i++)
        dist[i]=LLONG_MAX;
    pushh(1, 0);
    while (size){
        pair p=extract_min();
        ll u=p.v;
        for (list *a=g[u]; a; a=a->next){
            pair v=a->p;
            if (dist[u]+v.w<dist[v.v]){
                dist[v.v]=dist[u]+v.w;
                prev[v.v]=u;
                pushh(v.v, v.w);
            }
        }
    }
}
int main(){
    scanf("%I64d%I64d", &n, &m);
    while (m--){
        scanf("%I64d%I64d%I64d", &a, &b, &w);
        pushg(a, b, w);
        pushg(b, a, w);
    }
    dijkstra();

    if (!prev[n]){
    	printf("-1");
    	return 0;
    }
    prev[1]=0;
    a=n;
    if (prev[a])
    	while (prev[a]){
    		ans[ind]=a;
    		a=prev[a];
    		ind++;
    	}
    printf("1 ");
    for (ll i=ind-1; i>=0; i--)
    	printf("%I64d ", ans[i]);
}


#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 222222
typedef long long ll;
typedef struct {ll v, w;} pair;
typedef struct _list{
    pair p;
    struct _list *next;
} list;
list *g[N];
ll n, m, a, b, w, size, dist[N], prev[N], ans[N], ind;
pair pq[N];
void min_heapify(ll ind){
    ll l=ind*2, r=l+1, lowest=ind;
    if (l<=size&&(pq[l].v<pq[ind].v||pq[l].w<pq[ind].w))
        lowest=l;
    if (r<=size&&(pq[r].v<pq[ind].v||pq[r].w<pq[ind].w))
        lowest=r;
    if (lowest!=ind){
        pair tmp=pq[ind];
        pq[ind]=pq[lowest];
        pq[lowest]=tmp;
        min_heapify(lowest);
    }
}
pair extract_min(void){
    pair min=pq[1];
    pq[1]=pq[size];
    size--;
    min_heapify(1);
    return min;
}
void pushh(ll v, ll w){
    ++size;
    pq[size].v=v;
    pq[size].w=w;
    min_heapify(size);
}
void pushg(ll u, ll v, ll w){
    list *ptr=(list *) malloc(sizeof(list));
    ptr->next=g[u];
    ptr->p.v=v;
    ptr->p.w=w;
    g[u]=ptr;
}
int main(){
    scanf("%I64d%I64d", &n, &m);
    for (ll i=1; i<=n; i++)
        dist[i]=LLONG_MAX;
    while (m--){
        scanf("%I64d%I64d%I64d", &a, &b, &w);
        pushg(a, b, w);
        pushg(b, a, w);
    }
    pushh(1, 0);
    while (size){
        pair p=extract_min();
        for (list *a=g[p.v]; a; a=a->next){
            pair v=a->p;
            if (dist[p.v]+v.w<dist[v.v]){
                dist[v.v]=dist[p.v]+v.w;
                prev[v.v]=p.v
                pushh(v.v, v.w);
            }
        }
    }
    if (!prev[n]){
    	printf("-1");
    	return 0;
    }
    prev[1]=0;
    a=n;
    if (prev[a])
    	while (prev[a]){
    		ans[ind]=a;
    		a=prev[a];
    		ind++;
    	}
    printf("1 ");
    for (ll i=ind-1; i>=0; i--)
    	printf("%I64d ", ans[i]);
}


#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"
#include "limits.h"

long long inf = LLONG_MAX;

typedef struct vec
{
	int *arr;
	long long *wgt;
	int size;
	int cap;
} vec;

vec* g;

void push(vec* a, int val, long long w)
{
	if (a->cap == 0)
	{
		a->cap = 3;
		a->arr = (int*)malloc(3 * sizeof(int));
		a->wgt = (long long*)malloc(3 * sizeof(long long));
	}
	else if (a->size == a->cap)
	{
		a->cap = a->cap * 2 + 1;
		a->arr = (int*)realloc(a->arr, a->cap * sizeof(int));
		a->wgt = (long long*)realloc(a->wgt, a->cap * sizeof(long long));
	}
	a->arr[a->size] = val;
	a->wgt[a->size] = w;
	a->size++;
}

typedef struct node
{
	long long dist;
	int pos; //id in heap
} node;

int *heap;
node *val;
int *prev;
void build(int n, int k)
{
	heap = (int*)malloc(n * sizeof(int));
	val = (node*)malloc(n * sizeof(node));
	heap[0] = k;
	for (int i = 1; i <= k; i++)
	{
		heap[i] = i - 1;
	}
	for (int i = k + 1; i < n; i++)
	{
		heap[i] = i;
	}
	for (int i = 0; i < n; i++)
	{
		val[i].dist = inf;
		if (i < k)
		{
			val[i].pos = i + 1;
		}
		else if (i > k)
		{
			val[i].pos = i;
		}
	}
	val[k].dist = 0;
	val[k].pos = 0;
}

int pop(int size)
{
	int ans = heap[0];
	val[ans].pos = size - 1;
	int t = heap[0];
	heap[0] = heap[size - 1];
	heap[size - 1] = t;
	val[heap[0]].pos = 0;
	int p = 0;
	while (1)
	{
		if (p * 2 + 2 < size - 1)
		{
			if (val[heap[p * 2 + 2]].dist < val[heap[p * 2 + 1]].dist)
			{
				if (val[heap[p]].dist <= val[heap[p * 2 + 2]].dist)
				{
					break;
				}
				else
				{
					val[heap[p]].pos = p * 2 + 2;
					val[heap[p * 2 + 2]].pos = p;
					int t = heap[p];
					heap[p] = heap[p * 2 + 2];
					heap[p * 2 + 2] = t;
				}
			}
			else
			{
				if (val[heap[p]].dist <= val[heap[p * 2 + 1]].dist)
				{
					break;
				}
				else
				{
					val[heap[p]].pos = p * 2 + 1;
					val[heap[p * 2 + 1]].pos = p;
					int t = heap[p];
					heap[p] = heap[p * 2 + 1];
					heap[p * 2 + 1] = t;
				}
			}
		}
		else if (p * 2 + 1 < size + 1)
		{
			if (val[heap[p]].dist <= val[heap[p * 2 + 1]].dist)
			{
				break;
			}
			else
			{
				val[heap[p]].pos = p * 2 + 1;
				val[heap[p * 2 + 1]].pos = p;
				int t = heap[p];
				heap[p] = heap[p * 2 + 1];
				heap[p * 2 + 1] = t;
			}
		}
		else
		{
			break;
		}
	}
	return ans;
}

void update(int pos, long long newval, int size)
{
	val[pos].dist = newval;
	int p = val[pos].pos;
	while (1)
	{
		if (p > 0)
		{
			if (val[heap[p]].dist < val[heap[(p - 1) / 2]].dist)
			{
				val[heap[p]].pos = (p - 1) / 2;
				val[heap[(p - 1) / 2]].pos = p;
				int t = heap[p];
				heap[p] = heap[(p - 1) / 2];
				heap[(p - 1) / 2] = t;
				p = (p - 1) / 2;
				continue;
			}
		}
		break;
	}
}

int vprintp(int a)
{
	if (a == 0)
	{
		printf("1 ");
	}
	else
	{
		vprintp(prev[a]);
		printf("%d ", a + 1);
	}
}

int main()
{
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	int n, m;
	scanf("%d%d", &n, &m);
	int s = 1, t = n;
	//scanf("%d%d", &s, &t);
	prev = malloc(n * sizeof(int));
	g = (vec*)calloc(n, sizeof(vec));
	int *used = calloc(n, sizeof(int));
	used[s - 1] = 1;
	for (int i = 0; i < m; i++)
	{
		int u, v;
		long long w;
		scanf("%d%d%lld", &u, &v, &w);
		u--;
		v--;
		push(&g[u], v, w);
		push(&g[v], u, w);
	}
	build(n, s - 1);
	int size = n;
	while (size > 0)
	{
		int a = pop(size);
		long long dist = val[a].dist;
		size--;
		if (used[a] == 0) break;
		for (int i = 0; i < g[a].size; i++)
		{
			int to = g[a].arr[i];
			int w = g[a].wgt[i];
			if (val[to].dist > dist + w || !used[to])
			{
				used[to] = 1;
				update(to, dist + w, size);
				prev[to] = a;
			}
		}
	}
	if (used[t - 1] == 0)
	{
		printf("-1");
	}
	else
	{
		vprintp(n - 1);
		//printf("%lld", val[t - 1].dist);
	}
	free(g);
	free(heap);
	free(val);
	free(used);
	free(prev);
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"

long long inf = LLONG_MAX;

typedef struct vec
{
	int *arr;
	long long *wgt;
	int size;
	int cap;
} vec;

vec* g;

void push(vec* a, int val, long long w)
{
	if (a->cap == 0)
	{
		a->cap = 3;
		a->arr = (int*)malloc(3 * sizeof(int));
		a->wgt = (long long*)malloc(3 * sizeof(long long));
	}
	else if (a->size == a->cap)
	{
		a->cap = a->cap * 2 + 1;
		a->arr = (int*)realloc(a->arr, a->cap * sizeof(int));
		a->wgt = (long long*)realloc(a->wgt, a->cap * sizeof(long long));
	}
	a->arr[a->size] = val;
	a->wgt[a->size] = w;
	a->size++;
}

typedef struct node
{
	long long dist;
	int pos; //id in heap
} node;

int *heap;
node *val;
int *prev;
void build(int n, int k)
{
	heap = (int*)malloc(n * sizeof(int));
	val = (node*)malloc(n * sizeof(node));
	heap[0] = k;
	for (int i = 1; i <= k; i++)
	{
		heap[i] = i - 1;
	}
	for (int i = k + 1; i < n; i++)
	{
		heap[i] = i;
	}
	for (int i = 0; i < n; i++)
	{
		val[i].dist = inf;
		if (i < k)
		{
			val[i].pos = i + 1;
		}
		else if (i > k)
		{
			val[i].pos = i;
		}
	}
	val[k].dist = 0;
	val[k].pos = 0;
}

int pop(int size)
{
	int ans = heap[0];
	val[ans].pos = size - 1;
	int t = heap[0];
	heap[0] = heap[size - 1];
	heap[size - 1] = t;
	val[heap[0]].pos = 0;
	int p = 0;
	while (1)
	{
		if (p * 2 + 2 < size - 1)
		{
			if (val[heap[p * 2 + 2]].dist < val[heap[p * 2 + 1]].dist)
			{
				if (val[heap[p]].dist <= val[heap[p * 2 + 2]].dist)
				{
					break;
				}
				else
				{
					val[heap[p]].pos = p * 2 + 2;
					val[heap[p * 2 + 2]].pos = p;
					int t = heap[p];
					heap[p] = heap[p * 2 + 2];
					heap[p * 2 + 2] = t;
				}
			}
			else
			{
				if (val[heap[p]].dist <= val[heap[p * 2 + 1]].dist)
				{
					break;
				}
				else
				{
					val[heap[p]].pos = p * 2 + 1;
					val[heap[p * 2 + 1]].pos = p;
					int t = heap[p];
					heap[p] = heap[p * 2 + 1];
					heap[p * 2 + 1] = t;
				}
			}
		}
		else if (p * 2 + 1 < size + 1)
		{
			if (val[heap[p]].dist <= val[heap[p * 2 + 1]].dist)
			{
				break;
			}
			else
			{
				val[heap[p]].pos = p * 2 + 1;
				val[heap[p * 2 + 1]].pos = p;
				int t = heap[p];
				heap[p] = heap[p * 2 + 1];
				heap[p * 2 + 1] = t;
			}
		}
		else
		{
			break;
		}
	}
	return ans;
}

void update(int pos, long long newval, int size)
{
	val[pos].dist = newval;
	int p = val[pos].pos;
	while (1)
	{
		if (p > 0)
		{
			if (val[heap[p]].dist < val[heap[(p - 1) / 2]].dist)
			{
				val[heap[p]].pos = (p - 1) / 2;
				val[heap[(p - 1) / 2]].pos = p;
				int t = heap[p];
				heap[p] = heap[(p - 1) / 2];
				heap[(p - 1) / 2] = t;
				p = (p - 1) / 2;
				continue;
			}
		}
		break;
	}
}

int vprintp(int a)
{
	if (a == 0)
	{
		printf("1 ");
	}
	else
	{
		vprintp(prev[a]);
		printf("%d ", a + 1);
	}
}

int main()
{
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	int n, m;
	scanf("%d%d", &n, &m);
	int s = 1, t = n;
	//scanf("%d%d", &s, &t);
	prev = malloc(n * sizeof(int));
	g = (vec*)calloc(n, sizeof(vec));
	int *used = calloc(n, sizeof(int));
	used[s - 1] = 1;
	for (int i = 0; i < m; i++)
	{
		int u, v;
		long long w;
		scanf("%d%d%lld", &u, &v, &w);
		u--;
		v--;
		push(&g[u], v, w);
		push(&g[v], u, w);
	}
	build(n, s - 1);
	int size = n;
	while (size > 0)
	{
		int a = pop(size);
		long long dist = val[a].dist;
		size--;
		if (used[a] == 0) break;
		for (int i = 0; i < g[a].size; i++)
		{
			int to = g[a].arr[i];
			int w = g[a].wgt[i];
			if (val[to].dist > dist + w || !used[to])
			{
				used[to] = 1;
				update(to, dist + w, size);
				prev[to] = a;
			}
		}
	}
	if (used[t - 1] == 0)
	{
		printf("-1");
	}
	else
	{
		vprintp(n - 1);
		//printf("%lld", val[t - 1].dist);
	}
	free(g);
	free(heap);
	free(val);
	free(used);
	free(prev);
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"
#include "limits.h"

long long inf = LLONG_MAX;

typedef struct vec
{
	int *arr;
	long long *wgt;
	int size;
	int cap;
} vec;

vec* g;

void push(vec* a, int val, long long w)
{
	if (a->cap == 0)
	{
		a->cap = 3;
		a->arr = (int*)malloc(3 * sizeof(int));
		a->wgt = (long long*)malloc(3 * sizeof(long long));
	}
	else if (a->size == a->cap)
	{
		a->cap = a->cap * 2 + 1;
		a->arr = (int*)realloc(a->arr, a->cap * sizeof(int));
		a->wgt = (long long*)realloc(a->wgt, a->cap * sizeof(long long));
	}
	a->arr[a->size] = val;
	a->wgt[a->size] = w;
	a->size++;
}

typedef struct node
{
	long long dist;
	int pos; //id in heap
} node;

int *heap;
node *val;
int *prev;
void build(int n, int k)
{
	heap = (int*)malloc(n * sizeof(int));
	val = (node*)malloc(n * sizeof(node));
	heap[0] = k;
	for (int i = 1; i <= k; i++)
	{
		heap[i] = i - 1;
	}
	for (int i = k + 1; i < n; i++)
	{
		heap[i] = i;
	}
	for (int i = 0; i < n; i++)
	{
		val[i].dist = inf;
		if (i < k)
		{
			val[i].pos = i + 1;
		}
		else if (i > k)
		{
			val[i].pos = i;
		}
	}
	val[k].dist = 0;
	val[k].pos = 0;
}

int pop(int size)
{
	int ans = heap[0];
	val[ans].pos = size - 1;
	int t = heap[0];
	heap[0] = heap[size - 1];
	heap[size - 1] = t;
	val[heap[0]].pos = 0;
	int p = 0;
	while (1)
	{
		long long v1 = val[heap[p]].dist;
		long long v2, v3;
		if (p * 2 + 1 < size - 1)
		{
			v2 = val[heap[p * 2 + 1]].dist;
		}
		else
		{
			v2 = LLONG_MAX;
		}
		if (p * 2 + 2 < size - 1)
		{
			v3 = val[heap[p * 2 + 2]].dist;
		}
		else
		{
			v2 = LLONG_MAX;
		}

		if (v1 <= v2 && v1 <= v3)
		{
			break;
		}

		if (v2 < v3)
		{
			val[heap[p]].pos = p * 2 + 1;
			val[heap[p * 2 + 1]].pos = p;
			int t = heap[p];
			heap[p] = heap[p * 2 + 1];
			heap[p * 2 + 1] = t;
		}
		else
		{
			val[heap[p]].pos = p * 2 + 2;
			val[heap[p * 2 + 2]].pos = p;
			int t = heap[p];
			heap[p] = heap[p * 2 + 2];
			heap[p * 2 + 2] = t;
		}
	}
	return ans;
}

void update(int pos, long long newval, int size)
{
	val[pos].dist = newval;
	int p = val[pos].pos;
	while (1)
	{
		if (p > 0)
		{
			int p1 = heap[p];
			int p2 = heap[(p - 1) / 2];
			if (val[p1].dist < val[p2].dist)
			{
				val[p1].pos = (p - 1) / 2;
				val[p2].pos = p;
				int t = heap[p];
				heap[p] = heap[(p - 1) / 2];
				heap[(p - 1) / 2] = t;
				p = (p - 1) / 2;
				continue;
			}
		}
		break;
	}
}

int vprintp(int a)
{
	if (a == 0)
	{
		printf("1 ");
	}
	else
	{
		vprintp(prev[a]);
		printf("%d ", a + 1);
	}
}

int main()
{
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	int n, m;
	scanf("%d%d", &n, &m);
	int s = 1, t = n;
	//scanf("%d%d", &s, &t);
	prev = malloc(n * sizeof(int));
	g = (vec*)calloc(n, sizeof(vec));
	int *used = calloc(n, sizeof(int));
	used[s - 1] = 1;
	for (int i = 0; i < m; i++)
	{
		int u, v;
		long long w;
		scanf("%d%d%lld", &u, &v, &w);
		u--;
		v--;
		push(&g[u], v, w);
		push(&g[v], u, w);
	}
	build(n, s - 1);
	int size = n;
	while (size > 0)
	{
		int a = pop(size);
		if (used[a] == 0) break;
		long long dist = val[a].dist;
		size--;
		for (int i = 0; i < g[a].size; i++)
		{
			int to = g[a].arr[i];
			int w = g[a].wgt[i];
			if (val[to].dist > dist + w || !used[to])
			{
				used[to] = 1;
				update(to, dist + w, size);
				prev[to] = a;
			}
		}
	}
	if (used[t - 1] == 0)
	{
		printf("-1");
	}
	else
	{
		vprintp(n - 1);
		//printf("%lld", val[t - 1].dist);
	}
	free(g);
	free(heap);
	free(val);
	free(used);
	free(prev);
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"
#include "limits.h"

long long inf = LLONG_MAX;

typedef struct vec
{
	int *arr;
	long long *wgt;
	int size;
	int cap;
} vec;

vec* g;

void push(vec* a, int val, long long w)
{
	if (a->cap == 0)
	{
		a->cap = 3;
		a->arr = (int*)malloc(3 * sizeof(int));
		a->wgt = (long long*)malloc(3 * sizeof(long long));
	}
	else if (a->size == a->cap)
	{
		a->cap = a->cap * 2 + 1;
		a->arr = (int*)realloc(a->arr, a->cap * sizeof(int));
		a->wgt = (long long*)realloc(a->wgt, a->cap * sizeof(long long));
	}
	a->arr[a->size] = val;
	a->wgt[a->size] = w;
	a->size++;
}

typedef struct node
{
	long long dist;
	int pos; //id in heap
} node;

int *heap;
node *val;
int *prev;
void build(int n, int k)
{
	heap = (int*)malloc(n * sizeof(int));
	val = (node*)malloc(n * sizeof(node));
	heap[0] = k;
	for (int i = 1; i <= k; i++)
	{
		heap[i] = i - 1;
	}
	for (int i = k + 1; i < n; i++)
	{
		heap[i] = i;
	}
	for (int i = 0; i < n; i++)
	{
		val[i].dist = inf;
		if (i < k)
		{
			val[i].pos = i + 1;
		}
		else if (i > k)
		{
			val[i].pos = i;
		}
	}
	val[k].dist = 0;
	val[k].pos = 0;
}

int pop(int size)
{
	int ans = heap[0];
	val[ans].pos = size - 1;
	int t = heap[0];
	heap[0] = heap[size - 1];
	heap[size - 1] = t;
	val[heap[0]].pos = 0;
	int p = 0;
	while (1)
	{
		long long v1 = val[heap[p]].dist;
		long long v2, v3;
		if (p * 2 + 1 < size - 1)
		{
			v2 = val[heap[p * 2 + 1]].dist;
		}
		else
		{
			v2 = LLONG_MAX;
		}
		if (p * 2 + 2 < size - 1)
		{
			v3 = val[heap[p * 2 + 2]].dist;
		}
		else
		{
			v3 = LLONG_MAX;
		}

		if (v1 <= v2 && v1 <= v3)
		{
			break;
		}

		if (v2 < v3)
		{
			val[heap[p]].pos = p * 2 + 1;
			val[heap[p * 2 + 1]].pos = p;
			int t = heap[p];
			heap[p] = heap[p * 2 + 1];
			heap[p * 2 + 1] = t;
			p = p * 2 + 1;
		}
		else
		{
			val[heap[p]].pos = p * 2 + 2;
			val[heap[p * 2 + 2]].pos = p;
			int t = heap[p];
			heap[p] = heap[p * 2 + 2];
			heap[p * 2 + 2] = t;
			p = p * 2 + 2;
		}
	}
	return ans;
}

void update(int pos, long long newval, int size)
{
	val[pos].dist = newval;
	int p = val[pos].pos;
	while (1)
	{
		if (p > 0)
		{
			int p1 = heap[p];
			int p2 = heap[(p - 1) / 2];
			if (val[p1].dist < val[p2].dist)
			{
				val[p1].pos = (p - 1) / 2;
				val[p2].pos = p;
				int t = heap[p];
				heap[p] = heap[(p - 1) / 2];
				heap[(p - 1) / 2] = t;
				p = (p - 1) / 2;
				continue;
			}
		}
		break;
	}
}

int vprintp(int a)
{
	if (a == 0)
	{
		printf("1 ");
	}
	else
	{
		vprintp(prev[a]);
		printf("%d ", a + 1);
	}
}

int main()
{
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	int n, m;
	scanf("%d%d", &n, &m);
	int s = 1, t = n;
	//scanf("%d%d", &s, &t);
	prev = malloc(n * sizeof(int));
	g = (vec*)calloc(n, sizeof(vec));
	int *used = calloc(n, sizeof(int));
	used[s - 1] = 1;
	for (int i = 0; i < m; i++)
	{
		int u, v;
		long long w;
		scanf("%d%d%lld", &u, &v, &w);
		u--;
		v--;
		push(&g[u], v, w);
		push(&g[v], u, w);
	}
	build(n, s - 1);
	int size = n;
	while (size > 0)
	{
		int a = pop(size);
		if (used[a] == 0) break;
		long long dist = val[a].dist;
		size--;
		for (int i = 0; i < g[a].size; i++)
		{
			int to = g[a].arr[i];
			int w = g[a].wgt[i];
			if (val[to].dist > dist + w || !used[to])
			{
				used[to] = 1;
				update(to, dist + w, size);
				prev[to] = a;
			}
		}
	}
	if (used[t - 1] == 0)
	{
		printf("-1");
	}
	else
	{
		vprintp(n - 1);
		//printf("%lld", val[t - 1].dist);
	}
	free(g);
	free(heap);
	free(val);
	free(used);
	free(prev);
	return 0;
}


'use strict';

//const PriorityQueue = require('priorityqueuejs');

process.stdin.resume();
process.stdin.setEncoding('utf-8');

let inputString = '';
let currentLine = 0;
const INF = Math.pow(10, 12);

process.stdin.on('data', inputStdin => {
    inputString += inputStdin;
});

process.stdin.on('end', _ => {
    inputString = inputString.trim().split('\n').map(string => {
        return string.trim();
    });

    main();
});

function readline() {
    return inputString[currentLine++];
}

/**
 * Expose `PriorityQueue`.
 */
// module.exports = PriorityQueue;

/**
 * Initializes a new empty `PriorityQueue` with the given `comparator(a, b)`
 * function, uses `.DEFAULT_COMPARATOR()` when no function is provided.
 *
 * The comparator function must return a positive number when `a > b`, 0 when
 * `a == b` and a negative number when `a < b`.
 *
 * @param {Function}
 * @return {PriorityQueue}
 * @api public
 */

function PriorityQueue(comparator) {
  this._comparator = comparator || PriorityQueue.DEFAULT_COMPARATOR;
  this._elements = [];
}

PriorityQueue.DEFAULT_COMPARATOR = function(a, b) {
  if (typeof a === 'number' && typeof b === 'number') {
    return a - b;
  } else {
    a = a.toString();
    b = b.toString();

    if (a == b) return 0;

    return (a > b) ? 1 : -1;
  }
};

PriorityQueue.prototype.isEmpty = function() {
  return this.size() === 0;
};

PriorityQueue.prototype.peek = function() {
  if (this.isEmpty()) throw new Error('PriorityQueue is empty');

  return this._elements[0];
};

PriorityQueue.prototype.deq = function() {
  var first = this.peek();
  var last = this._elements.pop();
  var size = this.size();

  if (size === 0) return first;

  this._elements[0] = last;
  var current = 0;

  while (current < size) {
    var largest = current;
    var left = (2 * current) + 1;
    var right = (2 * current) + 2;

    if (left < size && this._compare(left, largest) >= 0) {
      largest = left;
    }

    if (right < size && this._compare(right, largest) >= 0) {
      largest = right;
    }

    if (largest === current) break;

    this._swap(largest, current);
    current = largest;
  }

  return first;
};

PriorityQueue.prototype.enq = function(element) {
  var size = this._elements.push(element);
  var current = size - 1;

  while (current > 0) {
    var parent = Math.floor((current - 1) / 2);

    if (this._compare(current, parent) <= 0) break;

    this._swap(parent, current);
    current = parent;
  }

  return size;
};

PriorityQueue.prototype.size = function() {
  return this._elements.length;
};

PriorityQueue.prototype.forEach = function(fn) {
  return this._elements.forEach(fn);
};

PriorityQueue.prototype._compare = function(a, b) {
  return this._comparator(this._elements[a], this._elements[b]);
};

PriorityQueue.prototype._swap = function(a, b) {
  var aux = this._elements[a];
  this._elements[a] = this._elements[b];
  this._elements[b] = aux;
};

let nodes, edges;
let edgeList = [];

const getInput = () => {
    const lineInput = readline().split(" ").map(Number);
    nodes = lineInput[0], edges = lineInput[1];

    edgeList = new Array(nodes + 1);
    for(let i  = 0; i < nodes + 1; i++){
        edgeList[i] = new Array();
        edgeList[i].push(0);
    }

    for(let i = 0; i < edges; i++){
        const lineInput = readline().split(" ").map(Number);
        let node1 = lineInput[0], node2 = lineInput[1], weight = lineInput[2];

        edgeList[node1].push({"to": node2, "weight": weight});
        edgeList[node2].push({"to": node1, "weight": weight});
    }
};

const dijkstra = (source, destination) => {
    let distance = new Array(nodes + 1).fill(INF);
    let pQueue = new PriorityQueue(function(v1, v2) {
        return v2.weight - v1.weight;
    });
    let visited = new Array(nodes + 1).fill(false);
    let parent = new Array(nodes + 1).fill(-1);

    distance[source] = 0;
    pQueue.enq({node: source, weight: 0});

    while(!pQueue.isEmpty()) {
        const { node, weight } = pQueue.peek();
        pQueue.deq();

        if(weight === INF)
            break;
        if(visited[node]) continue;
        visited[node] = true;

        for(let edge of edgeList[node]){
            const {to, weight: currentWeight } = edge;

            if(distance[to] > weight + currentWeight){
                distance[to] = weight + currentWeight;
                pQueue.enq({node: to, weight: distance[to]})
                parent[to] = node;
            }
        }

    }

    if(distance[destination] === INF)
        return "-1";

    let path = "";
    let currentNode = destination
    while(parent[currentNode] !== -1){
        path += currentNode.toString() + " ";
        currentNode = parent[currentNode];
    }
    path += currentNode.toString();
    path = path.split("").reverse().join("");

    return path;
}

function main() {
    getInput();
    const result = dijkstra(1, nodes);
    console.log(result);
}


'use strict';

//const PriorityQueue = require('priorityqueuejs');

process.stdin.resume();
process.stdin.setEncoding('utf-8');

let inputString = '';
let currentLine = 0;
const INF = Math.pow(10, 12);

process.stdin.on('data', inputStdin => {
    inputString += inputStdin;
});

process.stdin.on('end', _ => {
    inputString = inputString.trim().split('\n').map(string => {
        return string.trim();
    });

    main();
});

function readline() {
    return inputString[currentLine++];
}

/**
 * Expose `PriorityQueue`.
 */
// module.exports = PriorityQueue;

/**
 * Initializes a new empty `PriorityQueue` with the given `comparator(a, b)`
 * function, uses `.DEFAULT_COMPARATOR()` when no function is provided.
 *
 * The comparator function must return a positive number when `a > b`, 0 when
 * `a == b` and a negative number when `a < b`.
 *
 * @param {Function}
 * @return {PriorityQueue}
 * @api public
 */

function PriorityQueue(comparator) {
  this._comparator = comparator || PriorityQueue.DEFAULT_COMPARATOR;
  this._elements = [];
}

PriorityQueue.DEFAULT_COMPARATOR = function(a, b) {
  if (typeof a === 'number' && typeof b === 'number') {
    return a - b;
  } else {
    a = a.toString();
    b = b.toString();

    if (a == b) return 0;

    return (a > b) ? 1 : -1;
  }
};

PriorityQueue.prototype.isEmpty = function() {
  return this.size() === 0;
};

PriorityQueue.prototype.peek = function() {
  if (this.isEmpty()) throw new Error('PriorityQueue is empty');

  return this._elements[0];
};

PriorityQueue.prototype.deq = function() {
  var first = this.peek();
  var last = this._elements.pop();
  var size = this.size();

  if (size === 0) return first;

  this._elements[0] = last;
  var current = 0;

  while (current < size) {
    var largest = current;
    var left = (2 * current) + 1;
    var right = (2 * current) + 2;

    if (left < size && this._compare(left, largest) >= 0) {
      largest = left;
    }

    if (right < size && this._compare(right, largest) >= 0) {
      largest = right;
    }

    if (largest === current) break;

    this._swap(largest, current);
    current = largest;
  }

  return first;
};

PriorityQueue.prototype.enq = function(element) {
  var size = this._elements.push(element);
  var current = size - 1;

  while (current > 0) {
    var parent = Math.floor((current - 1) / 2);

    if (this._compare(current, parent) <= 0) break;

    this._swap(parent, current);
    current = parent;
  }

  return size;
};

PriorityQueue.prototype.size = function() {
  return this._elements.length;
};

PriorityQueue.prototype.forEach = function(fn) {
  return this._elements.forEach(fn);
};

PriorityQueue.prototype._compare = function(a, b) {
  return this._comparator(this._elements[a], this._elements[b]);
};

PriorityQueue.prototype._swap = function(a, b) {
  var aux = this._elements[a];
  this._elements[a] = this._elements[b];
  this._elements[b] = aux;
};

let nodes, edges;
let edgeList = [];

const getInput = () => {
    const lineInput = readline().split(" ").map(Number);
    nodes = lineInput[0], edges = lineInput[1];

    edgeList = new Array(nodes + 1);
    for(let i  = 0; i < nodes + 1; i++){
        edgeList[i] = new Array();
        edgeList[i].push(0);
    }

    for(let i = 0; i < edges; i++){
        const lineInput = readline().split(" ").map(Number);
        let node1 = lineInput[0], node2 = lineInput[1], weight = lineInput[2];

        edgeList[node1].push({"to": node2, "weight": weight});
        edgeList[node2].push({"to": node1, "weight": weight});
    }
};

const dijkstra = (source, destination) => {
    let distance = new Array(nodes + 1).fill(INF);
    let pQueue = new PriorityQueue(function(v1, v2) {
        return v2.weight - v1.weight;
    });
    let visited = new Array(nodes + 1).fill(false);
    let parent = new Array(nodes + 1).fill(-1);

    distance[source] = 0;
    pQueue.enq({node: source, weight: 0});

    while(!pQueue.isEmpty()) {
        const { node, weight } = pQueue.peek();
        pQueue.deq();

        if(weight === INF)
            break;
        if(visited[node]) continue;
        visited[node] = true;

        for(let edge of edgeList[node]){
            const {to, weight: currentWeight } = edge;

            if(distance[to] > weight + currentWeight){
                distance[to] = weight + currentWeight;
                pQueue.enq({node: to, weight: distance[to]})
                parent[to] = node;
            }
        }

    }

    if(distance[destination] === INF)
        return "-1";

    let path = "";
    let currentNode = destination
    while(parent[currentNode] !== -1){
        path += currentNode.toString() + " ";
        currentNode = parent[currentNode];
    }
    path += currentNode.toString();
    path = path.split(" ").reverse().join(" ");

    return path;
}

function main() {
    getInput();
    const result = dijkstra(1, nodes);
    console.log(result);
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharp
{
    public class _20C
    {
        public static void Main()
        {
            string[] tokens = Console.ReadLine().Split();

            int n = int.Parse(tokens[0]);
            int m = int.Parse(tokens[1]);

            var edges = Enumerable.Range(0, n).Select(i => new Dictionary<int, int>()).ToArray();

            for (int i = 0; i < m; i++)
            {
                tokens = Console.ReadLine().Split();

                int a = int.Parse(tokens[0]) - 1;
                int b = int.Parse(tokens[1]) - 1;
                int w = int.Parse(tokens[2]);

                if (!edges[a].ContainsKey(b) || w < edges[a][b])
                {
                    edges[a][b] = w;
                }

                if (!edges[b].ContainsKey(a) || w < edges[b][a])
                {
                    edges[b][a] = w;
                }
            }

            bool[] visited = new bool[n];
            int[] distance = new int[n];
            int?[] previous = new int?[n];
            var heap = new SortedDictionary<int, List<int>>();

            int current = n - 1;
            visited[current] = true;
            distance[current] = 0;
            previous[current] = null;
            heap[0] = new List<int> { current };

            while (heap.Any())
            {
                int key = heap.Keys.First();

                if (!heap[key].Any())
                {
                    heap.Remove(key);
                    continue;
                }

                current = heap[key].First();
                heap[key].Remove(current);

                foreach (var next in edges[current])
                {
                    if (visited[next.Key])
                    {
                        if (key + next.Value < distance[next.Key])
                        {
                            heap[distance[next.Key]].Remove(next.Key);
                        }
                        else
                        {
                            continue;
                        }
                    }

                    visited[next.Key] = true;
                    distance[next.Key] = key + next.Value;
                    previous[next.Key] = current;

                    if (!heap.ContainsKey(distance[next.Key]))
                    {
                        heap[distance[next.Key]] = new List<int>();
                    }

                    heap[distance[next.Key]].Add(next.Key);
                }
            }

            if (visited[0])
            {
                current = 0;
                var path = new List<int>() { current + 1 };

                while (previous[current] != null)
                {
                    current = previous[current].Value;
                    path.Add(current + 1);
                }

                Console.WriteLine(string.Join(" ", path));
            }
            else
            {
                Console.WriteLine(-1);
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharp
{
    public class _20C
    {
        public static void Main()
        {
            string[] tokens = Console.ReadLine().Split();

            int n = int.Parse(tokens[0]);
            int m = int.Parse(tokens[1]);

            var edges = Enumerable.Range(0, n).Select(i => new Dictionary<int, int>()).ToArray();

            for (int i = 0; i < m; i++)
            {
                tokens = Console.ReadLine().Split();

                int a = int.Parse(tokens[0]) - 1;
                int b = int.Parse(tokens[1]) - 1;
                int w = int.Parse(tokens[2]);

                if (!edges[a].ContainsKey(b) || w < edges[a][b])
                {
                    edges[a][b] = w;
                }

                if (!edges[b].ContainsKey(a) || w < edges[b][a])
                {
                    edges[b][a] = w;
                }
            }

            bool[] visited = new bool[n];
            long[] distance = new long[n];
            int?[] previous = new int?[n];
            var heap = new SortedDictionary<long, List<int>>();

            int current = n - 1;
            visited[current] = true;
            distance[current] = 0;
            previous[current] = null;
            heap[0] = new List<int> { current };

            while (heap.Any())
            {
                long key = heap.Keys.First();

                if (!heap[key].Any())
                {
                    heap.Remove(key);
                    continue;
                }

                current = heap[key].First();
                heap[key].Remove(current);

                foreach (var next in edges[current])
                {
                    if (visited[next.Key])
                    {
                        if (key + next.Value < distance[next.Key])
                        {
                            heap[distance[next.Key]].Remove(next.Key);
                        }
                        else
                        {
                            continue;
                        }
                    }

                    visited[next.Key] = true;
                    distance[next.Key] = key + next.Value;
                    previous[next.Key] = current;

                    if (!heap.ContainsKey(distance[next.Key]))
                    {
                        heap[distance[next.Key]] = new List<int>();
                    }

                    heap[distance[next.Key]].Add(next.Key);
                }
            }

            if (visited[0])
            {
                current = 0;
                var path = new List<int>() { current + 1 };

                while (previous[current] != null)
                {
                    current = previous[current].Value;
                    path.Add(current + 1);
                }

                Console.WriteLine(string.Join(" ", path));
            }
            else
            {
                Console.WriteLine(-1);
            }
        }
    }
}


using System;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Threading;
using System.Collections.Generic;

class Program
{
	class cmp: IComparer<int>
	{
		public cmp(long[] v)
		{
			m_v = v;
		}

		public int Compare(int v1, int v2)
		{
			return Comparer<long>.Default.Compare(m_v[v1], m_v[v2]);
		}

		long[] m_v;
	}

	static void Main()
	{
		Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

		string[] p = Console.ReadLine().Split(' ');
		int n = int.Parse(p[0]);
		int m = int.Parse(p[1]);

		List<int>[] g = new List<int>[n];
		List<int>[] c = new List<int>[n];
		for(int i = 0; i < n; ++i)
		{
			g[i] = new List<int>();
			c[i] = new List<int>();
		}

		for(int i = 0; i < m; ++i)
		{
			p = Console.ReadLine().Split(' ');
			int u = int.Parse(p[0]);
			int v = int.Parse(p[1]);
			int w = int.Parse(p[2]);

			if (--u != --v)
			{
				g[u].Add(v);
				c[u].Add(w);
				g[v].Add(u);
				c[v].Add(w);
			}
		}

		long[] d = new long[n];
		int[] from = new int[n];
		for(int i = 0; i < n; ++i)
		{
			d[i] = long.MaxValue;
		}
		d[n - 1] = 0;

		SortedSet<int> s = new SortedSet<int>(new cmp(d));
		s.Add(n - 1);

		while (s.Count > 0)
		{
			int u = s.Min;

			for(int i = 0; i < g[u].Count; ++i)
			{
				int v = g[u][i];
				int w = c[u][i];

				if (d[v] > d[u] + w)
				{
					s.Remove(v);
					d[v] = d[u] + w;
					from[v] = u;
					s.Add(v);
				}
			}

			s.Remove(u);
		}

		if (d[0] == long.MaxValue)
		{
			Console.WriteLine(-1);
		}
		else
		{
			int f = 0;
			while (f != n - 1)
			{
				Console.Write("{0} ", f + 1);
				f = from[f];
			}
			Console.WriteLine(f + 1);
		}
	}
}


using System;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Threading;
using System.Collections.Generic;

class Program
{
	class cmp: IComparer<int>
	{
		public cmp(long[] v)
		{
			m_v = v;
		}

		public int Compare(int v1, int v2)
		{
			int res = Comparer<long>.Default.Compare(m_v[v1], m_v[v2]);
			if (res == 0)
			{
				res = v1 - v2;
			}
			return res;
		}

		long[] m_v;
	}

	static void Main()
	{
		Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

		string[] p = Console.ReadLine().Split(' ');
		int n = int.Parse(p[0]);
		int m = int.Parse(p[1]);

		List<int>[] g = new List<int>[n];
		List<int>[] c = new List<int>[n];
		for(int i = 0; i < n; ++i)
		{
			g[i] = new List<int>();
			c[i] = new List<int>();
		}

		for(int i = 0; i < m; ++i)
		{
			p = Console.ReadLine().Split(' ');
			int u = int.Parse(p[0]);
			int v = int.Parse(p[1]);
			int w = int.Parse(p[2]);

			if (--u != --v)
			{
				g[u].Add(v);
				c[u].Add(w);
				g[v].Add(u);
				c[v].Add(w);
			}
		}

		long[] d = new long[n];
		int[] from = new int[n];
		for(int i = 0; i < n; ++i)
		{
			d[i] = long.MaxValue;
		}
		d[n - 1] = 0;

		SortedDictionary<int, int> s = new SortedDictionary<int, int>(new cmp(d));
		s.Add(n - 1, 0);

		while (s.Count > 0)
		{
			var en = s.Keys.GetEnumerator();
			en.MoveNext();
			int u = en.Current;

			for(int i = 0; i < g[u].Count; ++i)
			{
				int v = g[u][i];
				int w = c[u][i];

				if (d[v] > d[u] + w)
				{
					s.Remove(v);
					d[v] = d[u] + w;
					from[v] = u;
					s.Add(v, 0);
				}
			}

			s.Remove(u);
		}

		if (d[0] == long.MaxValue)
		{
			Console.WriteLine(-1);
		}
		else
		{
			int f = 0;
			while (f != n - 1)
			{
				Console.Write("{0} ", f + 1);
				f = from[f];
			}
			Console.WriteLine(f + 1);
		}
	}
}