#include <bits/stdc++.h>
using namespace std;
const int MAXN = (int)1e5 + 10;
const int MAXA = (int)1e5 + 200;
const int MOD = (int)1e9 + 7;
int n, m, s, t;
vector<pair<int, int> > adj[MAXN];
int d[MAXN], f[MAXN];
int p[MAXN];
long long e[MAXA + 10];
struct SegmentTree {
  int t_size;
  int hash[MAXA * 100];
  int lazy[MAXA * 100];
  int l_child[MAXA * 100];
  int r_child[MAXA * 100];
  void merge(int k, int l, int r) {
    hash[k] =
        (hash[l_child[k]] + e[((l + r) >> 1) - l + 1] * hash[r_child[k]]) % MOD;
  }
  int init(int l, int r) {
    int k = ++t_size;
    if (l == r) {
      hash[k] = 0;
      lazy[k] = -1;
      return k;
    }
    l_child[k] = init(l, ((l + r) >> 1));
    r_child[k] = init(((l + r) >> 1) + 1, r);
    lazy[k] = -1;
    merge(k, l, r);
    return k;
  }
  int new_node(int node, int l, int r, int v) {
    int k = ++t_size;
    l_child[k] = l_child[node];
    r_child[k] = r_child[node];
    lazy[k] = v;
    hash[k] = v * (e[r - l + 1] - 1);
    return k;
  }
  void propagate(int k, int l, int r) {
    int v = lazy[k];
    lazy[k] = -1;
    if (v == -1) {
      return;
    }
    l_child[k] = new_node(l_child[k], l, ((l + r) >> 1), v);
    r_child[k] = new_node(r_child[k], ((l + r) >> 1) + 1, r, v);
  }
  int update(int k, int l, int r, int i, int j, int v) {
    if (l > j || r < i) {
      return k;
    }
    if (i <= l && r <= j) {
      int k1 = ++t_size;
      hash[k1] = v * (e[r - l + 1] - 1);
      lazy[k1] = v;
      l_child[k1] = l_child[k];
      r_child[k1] = r_child[k];
      return k1;
    }
    int k1 = ++t_size;
    propagate(k, l, r);
    l_child[k1] = update(l_child[k], l, ((l + r) >> 1), i, j, v);
    r_child[k1] = update(r_child[k], ((l + r) >> 1) + 1, r, i, j, v);
    lazy[k1] = -1;
    merge(k1, l, r);
    return k1;
  }
  int get_hash(int k, int l, int r, int i, int j) {
    if (l == i && r == j) {
      return hash[k];
    }
    propagate(k, l, r);
    if (j <= ((l + r) >> 1)) {
      return get_hash(l_child[k], l, ((l + r) >> 1), i, j);
    }
    if (i > ((l + r) >> 1)) {
      return get_hash(r_child[k], ((l + r) >> 1) + 1, r, i, j);
    }
    int l_hash = get_hash(l_child[k], l, ((l + r) >> 1), i, ((l + r) >> 1));
    int r_hash =
        get_hash(r_child[k], ((l + r) >> 1) + 1, r, ((l + r) >> 1) + 1, j);
    return (l_hash + e[((l + r) >> 1) - i + 1] * r_hash) % MOD;
  }
} pst;
int find_next_zero(int root, int p) {
  int l = p, r = MAXA, f = -1;
  while (l <= r) {
    int mid = (l + r) >> 1;
    if (pst.get_hash(root, 1, MAXA, p, mid) != (e[mid - p + 1] - 1)) {
      f = mid;
      r = mid - 1;
    } else {
      l = mid + 1;
    }
  }
  return f;
}
bool compare(int x, int y) {
  if (x == y || pst.hash[x] == pst.hash[y]) {
    return false;
  }
  int l = 1, r = MAXA;
  while (l < r) {
    int mid = (l + r) >> 1;
    pst.propagate(x, l, r);
    pst.propagate(y, l, r);
    if (pst.hash[pst.r_child[x]] != pst.hash[pst.r_child[y]]) {
      x = pst.r_child[x];
      y = pst.r_child[y];
      l = mid + 1;
    } else {
      x = pst.l_child[x];
      y = pst.l_child[y];
      r = mid;
    }
  }
  return pst.hash[x] < pst.hash[y];
}
int add(int root, int p) {
  int next_zero = find_next_zero(root, p);
  root = pst.update(root, 1, MAXA, next_zero, next_zero, 1);
  if (p < next_zero) {
    root = pst.update(root, 1, MAXA, p, next_zero - 1, 0);
  }
  return root;
}
struct State {
  int dist;
  int vertex;
  State(int dist, int vertex) : dist(dist), vertex(vertex){};
  bool operator<(const State &s) const {
    if (dist != s.dist) {
      return compare(s.dist, dist);
    }
    return vertex < s.vertex;
  }
};
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; ++i) {
    int u, v, w;
    scanf("%d%d%d", &u, &v, &w);
    w += 1;
    adj[u].push_back(pair<int, int>(v, w));
    adj[v].push_back(pair<int, int>(u, w));
  }
  scanf("%d%d", &s, &t);
  e[0] = 1;
  for (int i = 1; i <= MAXA; ++i) {
    e[i] = e[i - 1] * 2 % MOD;
  }
  int zero = pst.init(1, MAXA);
  int inf = pst.update(zero, 1, MAXA, 1, MAXA, 1);
  priority_queue<State> pq;
  for (int i = 1; i <= n; ++i) {
    d[i] = inf;
    p[i] = -1;
  }
  pq.push(State(zero, s));
  d[s] = zero;
  p[s] = -2;
  f[s] = 0;
  while (pq.size()) {
    int u = pq.top().vertex;
    int t = pq.top().dist;
    pq.pop();
    if (compare(d[u], t)) {
      continue;
    }
    for (int i = 0; i < (int)adj[u].size(); ++i) {
      int v = adj[u][i].first;
      int w = adj[u][i].second;
      int tmp = add(d[u], w);
      if (compare(tmp, d[v])) {
        d[v] = tmp;
        f[v] = (f[u] + e[w - 1]) % MOD;
        p[v] = u;
        pq.push(State(d[v], v));
      }
    }
  }
  if (p[t] == -1) {
    puts("-1");
    return 0;
  }
  vector<int> path;
  for (int u = t; u != -2; u = p[u]) {
    path.push_back(u);
  }
  reverse(path.begin(), path.end());
  printf("%d\n", f[t]);
  printf("%d\n", (int)path.size());
  for (int i = 0; i < (int)path.size(); ++i) {
    printf("%d ", path[i]);
  }
  puts("");
  return 0;
}
