#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const long long INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 200000 + 10;
const double eps = 1e-9;
struct Edge {
  int to, next, w;
  Edge() {}
} edge[maxn << 1];
int head[maxn], tot;
unsigned int seed = 131, f[maxn], H[maxn];
int f2[maxn];
void init() {
  memset(head, -1, sizeof(head));
  tot = 0;
  f[0] = f2[0] = 1;
  for (int i = 1; i < maxn; i++) {
    f[i] = f[i - 1] * seed;
    H[i] = H[i - 1] * seed + 1;
    f2[i] = 1ll * f2[i - 1] * 2 % mod;
  }
}
void addedge(int u, int v, int w) {
  edge[tot].to = v;
  edge[tot].next = head[u];
  edge[tot].w = w;
  head[u] = tot++;
}
int T[2], lson[maxn * 60], rson[maxn * 60];
unsigned int tree[maxn * 60];
int tol;
void pushup(int o, int L, int R) {
  int l = lson[o], r = rson[o], M = L + (R - L) / 2;
  int len = M - L + 1;
  tree[o] = tree[r] * f[len] + tree[l];
}
int build(int L, int R, int val) {
  int o = tol++;
  if (L == R) {
    tree[o] = val;
    return o;
  }
  int M = L + (R - L) / 2;
  lson[o] = build(L, M, val);
  rson[o] = build(M + 1, R, val);
  pushup(o, L, R);
  return o;
}
int N;
unsigned int get(int o, int L, int R, int l, int r) {
  if (l <= L && R <= r) {
    return tree[o];
  }
  int M = L + (R - L) / 2;
  unsigned int res = 0;
  if (l <= M) {
    res = get(lson[o], L, M, l, r);
    if (r > M) res += get(rson[o], M + 1, R, l, r) * f[M - l + 1];
  } else {
    res = get(rson[o], M + 1, R, l, r);
  }
  return res;
}
int add(int o, int L, int R, int x, int o1) {
  if (x == L && tree[o] == H[R - L + 1]) {
    return o1;
  }
  int u = tol++;
  if (L == R) {
    tree[u] = 1;
    return u;
  }
  int M = L + (R - L) / 2;
  if (x <= M) {
    if (get(o, L, R, x, M) == H[M - x + 1]) {
      lson[u] = add(lson[o], L, M, x, lson[o1]);
      rson[u] = add(rson[o], M + 1, R, M + 1, rson[o1]);
    } else {
      rson[u] = rson[o];
      lson[u] = add(lson[o], L, M, x, lson[o1]);
    }
  } else {
    lson[u] = lson[o];
    rson[u] = add(rson[o], M + 1, R, x, rson[o1]);
  }
  pushup(u, L, R);
  return u;
}
int cmp(int o1, int o2, int L, int R) {
  if (tree[o1] == tree[o2]) return 0;
  if (L == R) {
    if (tree[o1] > tree[o2]) return 1;
    return -1;
  }
  int M = L + (R - L) / 2;
  int l1 = lson[o1], l2 = lson[o2], r1 = rson[o1], r2 = rson[o2];
  if (tree[r1] == tree[r2]) return cmp(l1, l2, L, M);
  return cmp(r1, r2, M + 1, R);
}
struct node {
  int to, id;
  node(int to = 0, int id = 0) : to(to), id(id) {}
  bool operator<(const node &rhs) const { return cmp(id, rhs.id, 0, N) > 0; }
};
priority_queue<node> q;
bool vis[maxn];
int dis[maxn], pre[maxn];
void dij(int n, int s) {
  for (int i = 1; i <= n; i++) dis[i] = T[1];
  q.push(node(s, T[0]));
  dis[s] = T[0];
  while (!q.empty()) {
    node u = q.top();
    q.pop();
    if (vis[u.to]) continue;
    vis[u.to] = true;
    for (int i = head[u.to]; ~i; i = edge[i].next) {
      int v = edge[i].to;
      int tmp = add(dis[u.to], 0, N, edge[i].w, T[0]);
      if (cmp(dis[v], tmp, 0, N) > 0) {
        dis[v] = tmp;
        q.push(node(v, dis[v]));
        pre[v] = u.to;
      }
    }
  }
}
int get_ans(int o, int L, int R) {
  if (L == R) {
    return (int)tree[o];
  }
  int M = L + (R - L) / 2, res = 0;
  res = (1ll * get_ans(lson[o], L, M) +
         1ll * get_ans(rson[o], M + 1, R) * f2[M - L + 1] % mod) %
        mod;
  return res;
}
vector<int> path;
void get_path(int u) {
  if (!u) return;
  get_path(pre[u]);
  path.push_back(u);
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  init();
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    int u, v, w;
    cin >> u >> v >> w;
    addedge(u, v, w);
    addedge(v, u, w);
  }
  N = 200005;
  T[0] = build(0, N, 0);
  T[1] = build(0, N, 1);
  int s, t;
  cin >> s >> t;
  dij(n, s);
  if (dis[t] == T[1]) {
    cout << -1 << "\n";
    return 0;
  }
  cout << get_ans(dis[t], 0, N) << "\n";
  get_path(t);
  cout << path.size() << "\n";
  for (int u : path) cout << u << " ";
  cout << "\n";
  return 0;
}
