#include <bits/stdc++.h>
template <typename T>
inline void read(T &x) {
  x = 0;
  char c = getchar();
  bool flag = false;
  while (!isdigit(c)) {
    if (c == '-') flag = true;
    c = getchar();
  }
  while (isdigit(c)) x = x * 10 + (c ^ 48), c = getchar();
  if (flag) x = -x;
}
using namespace std;
const int up = 100050;
const int P = 1e9 + 7;
const int PP = 998244853;
const int base = 13331;
struct Hash {
  long long x, y;
  Hash() { x = y = 0; }
  Hash(long long jzp, long long zzz) { x = jzp, y = zzz; }
  inline Hash operator+(const Hash &a) const {
    return Hash((x + a.x) % P, (y + a.y) % PP);
  }
  inline Hash operator-(const Hash &a) const {
    return Hash((x - a.x + P) % P, (y - a.y + PP) % PP);
  }
  inline Hash operator*(const Hash &a) const {
    return Hash(x * a.x % P, y * a.y % PP);
  }
  inline bool operator==(const Hash &a) const { return x == a.x && y == a.y; }
} mi[101000];
inline void init() {
  mi[0] = Hash(1, 1);
  mi[1] = Hash(2, 2);
  for (int i = 2; i <= up; ++i) mi[i] = mi[i - 1] * mi[1];
}
int n, m;
struct edge {
  int nxt, to, val;
  edge() {}
  edge(int jzp, int zzz, int lsr) { nxt = jzp, to = zzz, val = lsr; }
} e[101000 << 1];
int head[101000], ecnt;
inline void addedge(int from, int to, int val) {
  e[++ecnt] = edge(head[from], to, val);
  head[from] = ecnt;
}
Hash ha[8001000];
int ls[8001000], rs[8001000], ttot;
bool isfull[8001000];
void ins(int L, int R, int pos, int lstcur, int &cur) {
  cur = ++ttot;
  ls[cur] = ls[lstcur];
  rs[cur] = rs[lstcur];
  ha[cur] = ha[lstcur] + mi[pos];
  if (L == R) return isfull[cur] = true, void();
  int mid = (L + R) >> 1;
  if (pos <= mid)
    ins(L, mid, pos, ls[lstcur], ls[cur]);
  else
    ins(mid + 1, R, pos, rs[lstcur], rs[cur]);
  isfull[cur] = isfull[ls[cur]] && isfull[rs[cur]];
}
inline void pushup(int cur) {
  ha[cur] = ha[ls[cur]] + ha[rs[cur]];
  isfull[cur] = isfull[ls[cur]] && isfull[rs[cur]];
}
void modify_set(int L, int R, int l, int r, int lstcur, int &cur) {
  if (l <= L && R <= r) return cur = 0, void();
  cur = ++ttot;
  ls[cur] = ls[lstcur];
  rs[cur] = rs[lstcur];
  int mid = (L + R) >> 1;
  if (l <= mid) modify_set(L, mid, l, r, ls[lstcur], ls[cur]);
  if (r > mid) modify_set(mid + 1, R, l, r, rs[lstcur], rs[cur]);
  pushup(cur);
}
int find_r(int L, int R, int l, int r, int cur) {
  if (!cur) return L - 1;
  if (isfull[cur]) return R;
  if (l <= L && R <= r) {
    int mid = (L + R) >> 1;
    if (isfull[ls[cur]])
      return find_r(mid + 1, R, l, r, rs[cur]);
    else
      return find_r(L, mid, l, r, ls[cur]);
  }
  int mid = (L + R) >> 1;
  if (l <= mid && r > mid) {
    int p = find_r(L, mid, l, r, ls[cur]);
    if (p == mid)
      return find_r(mid + 1, R, l, r, rs[cur]);
    else
      return p;
  }
  if (l <= mid)
    return find_r(L, mid, l, r, ls[cur]);
  else
    return find_r(mid + 1, R, l, r, rs[cur]);
}
bool dfscmp(int L, int R, int x, int y) {
  if (!x || !y) return x > y;
  if (L == R) return ha[x].x > ha[y].x;
  int mid = (L + R) >> 1;
  if (ha[rs[x]] == ha[rs[y]])
    return dfscmp(L, mid, ls[x], ls[y]);
  else
    return dfscmp(mid + 1, R, rs[x], rs[y]);
}
struct node {
  int cur, val;
  node() {}
  node(int jzp, int zzz) { cur = jzp, val = zzz; }
  inline bool operator<(const node &a) const {
    if (!val || !a.val) return val > a.val;
    return dfscmp(0, up, val, a.val);
  }
};
inline int Add(int lstcur, int v) {
  int r = find_r(0, up, v, up, lstcur);
  int cur = lstcur;
  if (r >= v)
    modify_set(0, up, v, r, cur, cur), ins(0, up, r + 1, cur, cur);
  else
    ins(0, up, v, cur, cur);
  return cur;
}
priority_queue<node> q;
int dis[101000], pre[101000];
bool vis[101000];
int ans[101000], atot;
inline void Push(int x) { ans[++atot] = x; }
inline void Print() {
  printf("%d\n", atot);
  for (int i = atot; i; --i) printf("%d ", ans[i]);
  puts("");
}
inline void dij() {
  int s, t;
  read(s), read(t);
  dis[s] = ++ttot;
  q.push(node(s, dis[s]));
  while (q.size()) {
    int cur = q.top().cur;
    q.pop();
    if (vis[cur]) continue;
    vis[cur] = true;
    if (cur == t) break;
    for (int i = head[cur]; i; i = e[i].nxt) {
      int to = e[i].to;
      if (vis[to]) continue;
      int r = Add(dis[cur], e[i].val);
      if (!dis[to] || dfscmp(0, up, dis[to], r))
        dis[to] = r, pre[to] = cur, q.push(node(to, r));
    }
  }
  if (!vis[t]) {
    puts("-1");
  } else {
    printf("%lld\n", (ha[dis[t]].x % P + P) % P);
    int p = t;
    while (p != s) {
      Push(p);
      p = pre[p];
    }
    Push(s);
    Print();
  }
}
int main() {
  init();
  read(n), read(m);
  for (int i = 1; i <= m; ++i) {
    int u, v, w;
    read(u), read(v), read(w);
    addedge(u, v, w), addedge(v, u, w);
  }
  dij();
  return 0;
}
