#include <bits/stdc++.h>
#pragma warning(disable : 4996)
template <typename T>
T min(T x, T y) {
  return x < y ? x : y;
}
template <typename T>
T max(T x, T y) {
  return x > y ? x : y;
};
const long long MAXN = 200005;
const long long mod = 1000000007;
long long po[MAXN + 5], h1[MAXN + 5];
struct tree {
  long long h;
  long long l;
  long long r;
  tree *lson;
  tree *rson;
  tree() {
    h = l = r = 0;
    lson = rson = NULL;
  }
  void fixup() { h = (rson->h * po[lson->r - lson->l + 1] + lson->h) % mod; }
  void build0(long long L, long long R) {
    l = L;
    r = R;
    h = 0;
    if (l == r) return;
    long long mid = (l + r) / 2;
    lson = new tree;
    rson = new tree;
    lson->build0(l, mid);
    rson->build0(mid + 1, r);
  }
  void build1(long long L, long long R) {
    l = L;
    r = R;
    if (l == r) {
      h = 1;
      return;
    }
    long long mid = (l + r) / 2;
    lson = new tree;
    rson = new tree;
    lson->build1(l, mid);
    rson->build1(mid + 1, r);
    fixup();
  }
  long long read(long long pos) {
    if (l == r) return h;
    long long mid = (l + r) / 2;
    return pos <= mid ? lson->read(pos) : rson->read(pos);
  }
  long long find0(long long L, long long R) {
    if (r < L || l > R || h == h1[r - l + 1]) return MAXN + 1;
    if (l == r) return l;
    long long t = lson->find0(L, R);
    if (t <= MAXN) return t;
    return rson->find0(L, R);
  }
};
tree *T0, *T1;
tree *set0(tree *T, tree *curT0, long long L, long long R) {
  if (T->l >= L && T->r <= R) return curT0;
  tree *p = new tree;
  *p = *T;
  long long mid = (p->l + p->r) / 2;
  if (L <= mid) p->lson = set0(p->lson, curT0->lson, L, R);
  if (R > mid) p->rson = set0(p->rson, curT0->rson, L, R);
  p->fixup();
  return p;
}
tree *set1(tree *T, tree *curT1, long long L, long long R) {
  if (T->l >= L && T->r <= R) return curT1;
  tree *p = new tree;
  *p = *T;
  long long mid = (p->l + p->r) / 2;
  if (L <= mid) p->lson = set1(T->lson, curT1->lson, L, R);
  if (R > mid) p->rson = set1(T->rson, curT1->rson, L, R);
  p->fixup();
  return p;
}
long long find(tree *X, tree *Y) {
  if (X->h == Y->h) return MAXN + 1;
  if (X->l == X->r) return X->l;
  long long t = find(X->rson, Y->rson);
  return t != MAXN + 1 ? t : find(X->lson, Y->lson);
}
struct number {
  tree *T;
  number() { T = T0; }
  number operator+(long long t) {
    number ret;
    if (T->read(t) == 0)
      ret.T = set1(T, T1, t, t);
    else {
      long long pos = T->find0(t, MAXN);
      ret.T = set0(T, T0, t, pos - 1);
      ret.T = set1(ret.T, T1, pos, pos);
    }
    return ret;
  }
  bool operator<(number t) const {
    long long pos = find(T, t.T);
    if (pos == MAXN + 1) return false;
    return T->read(pos) > t.T->read(pos);
  }
};
struct node {
  long long to;
  long long w;
  node *next;
};
void addnode(node *&head, long long to, long long w) {
  node *p = new node;
  p->to = to;
  p->w = w;
  p->next = head;
  head = p;
}
long long N, M;
node *edge[MAXN];
number dis[MAXN];
long long from[MAXN];
struct ele {
  long long id;
  number w;
  ele(long long x = 0, number y = number()) {
    id = x;
    w = y;
  }
  bool operator<(ele t) const { return w < t.w; }
};
std::priority_queue<ele> Q;
bool used[MAXN];
void dij(long long S) {
  for (long long i = 1; i <= N; i++) dis[i] = (dis[i] + MAXN);
  dis[S].T = T0;
  for (long long i = 1; i <= N; i++) Q.push(ele(i, dis[i]));
  while (!Q.empty()) {
    long long v = Q.top().id;
    Q.pop();
    if (used[v]) continue;
    used[v] = true;
    for (node *p = edge[v]; p; p = p->next)
      if (!used[p->to] && (dis[p->to] < (dis[v] + p->w)))
        dis[p->to] = dis[v] + p->w, from[p->to] = v,
        Q.push(ele(p->to, dis[p->to]));
  }
}
void init() {
  po[0] = 1;
  for (long long i = 1; i < MAXN; i++) po[i] = po[i - 1] * 2 % mod;
  h1[0] = 0;
  for (long long i = 1; i < MAXN; i++) h1[i] = (h1[i - 1] * 2 + 1) % mod;
  T0 = new tree;
  T1 = new tree;
  T0->build0(0, MAXN);
  T1->build1(0, MAXN);
  for (long long i = 0; i < MAXN; i++) dis[i] = number();
  long long u, v, w;
  scanf("%I64d %I64d", &N, &M);
  for (long long i = 1; i <= M; i++) {
    scanf("%I64d %I64d %I64d", &u, &v, &w);
    addnode(edge[u], v, w);
    addnode(edge[v], u, w);
  }
}
void solve() {
  long long s, t;
  scanf("%I64d %I64d", &s, &t);
  if (s == t) {
    printf("0\n1\n%d\n", s);
    return;
  }
  dij(s);
  if (!from[t]) {
    printf("-1\n");
    return;
  }
  printf("%I64d\n", dis[t].T->h);
  std::stack<long long> S;
  while (t) {
    S.push(t);
    t = from[t];
  }
  t = S.size();
  printf("%I64d\n", t);
  while (S.size()) printf("%I64d ", S.top()), S.pop();
}
void test() {
  number t;
  t.T = set1(t.T, T1, MAXN, MAXN);
}
int main() {
  init();
  solve();
  return 0;
}
