#include <bits/stdc++.h>
using namespace std;
template <typename T>
T gcd(T a, T b) {
  while (b > 0) {
    a %= b;
    swap(a, b);
  }
  return a;
}
template <class _T>
inline _T sqr(const _T &first) {
  return first * first;
}
template <class _T>
inline string tostr(const _T &a) {
  ostringstream os("");
  os << a;
  return os.str();
}
const long double PI = 3.1415926535897932384626433832795L;
const double EPS = 1e-9;
char TEMPORARY_CHAR;
const int INF = 1e9;
inline void input(int &a) {
  a = 0;
  while (((TEMPORARY_CHAR = getchar()) > '9' || TEMPORARY_CHAR < '0') &&
         (TEMPORARY_CHAR != '-')) {
  }
  char neg = 0;
  if (TEMPORARY_CHAR == '-') {
    neg = 1;
    TEMPORARY_CHAR = getchar();
  }
  while (TEMPORARY_CHAR <= '9' && TEMPORARY_CHAR >= '0') {
    a = 10 * a + TEMPORARY_CHAR - '0';
    TEMPORARY_CHAR = getchar();
  }
  if (neg) a = -a;
}
inline void out(long long a) {
  if (!a) putchar('0');
  if (a < 0) {
    putchar('-');
    a = -a;
  }
  char s[20];
  int i;
  for (i = 0; a; ++i) {
    s[i] = '0' + a % 10;
    a /= 10;
  }
  for (int j = (i)-1; j >= 0; j--) putchar(s[j]);
}
inline int nxt() {
  int(ret);
  input((ret));
  ;
  return ret;
}
struct node {
  node *l, *r;
  long long hash;
  long long pw;
  int zeroCount;
};
typedef node *inode;
inode ZERO, ONE;
inode pick(inode l, inode r) {
  inode res = new node();
  res->l = l, res->r = r;
  res->hash = l->hash * l->pw + r->hash;
  res->pw = l->pw * r->pw;
  res->zeroCount = l->zeroCount + r->zeroCount;
  return res;
}
inode build(int tl, int tr, int val) {
  if (tl == tr) {
    return val ? ONE : ZERO;
  }
  int tm = (tl + tr) >> 1;
  return pick(build(tl, tm, val), build(tm + 1, tr, val));
}
inode fillZeroes(inode v, inode zeroes, int tl, int tr, int l, int r) {
  if (l > r) {
    return v;
  }
  if (l == tl && r == tr) {
    return zeroes;
  }
  int tm = (tl + tr) >> 1;
  inode left = fillZeroes(v->l, zeroes->l, tl, tm, l, min(tm, r));
  inode right = fillZeroes(v->r, zeroes->r, tm + 1, tr, max(tm + 1, l), r);
  return pick(left, right);
}
inode setOne(inode v, int tl, int tr, int pos) {
  if (tl == tr) {
    return ONE;
  }
  int tm = (tl + tr) >> 1;
  inode left, right;
  if (pos <= tm) {
    left = setOne(v->l, tl, tm, pos);
    right = v->r;
  } else {
    left = v->l;
    right = setOne(v->r, tm + 1, tr, pos);
  }
  return pick(left, right);
}
int getZeroCount(inode v, int tl, int tr, int l, int r) {
  if (l > r) return 0;
  if (tl == l && tr == r) {
    return v->zeroCount;
  }
  int tm = (tl + tr) >> 1;
  int left = getZeroCount(v->l, tl, tm, l, min(tm, r));
  int right = getZeroCount(v->r, tm + 1, tr, max(tm + 1, l), r);
  return left + right;
}
int findKthZero(inode v, int tl, int tr, int k) {
  if (tl == tr) {
    return tl;
  }
  int tm = (tl + tr) >> 1;
  if (v->l->zeroCount >= k) {
    return findKthZero(v->l, tl, tm, k);
  } else {
    return findKthZero(v->r, tm + 1, tr, k - v->l->zeroCount);
  }
}
const int N = 131072;
inode zeroes;
inode ones;
inode add(inode v, int pos) {
  int zeroCount = getZeroCount(v, 0, N - 1, 0, pos - 1);
  int kthZero = findKthZero(v, 0, N - 1, zeroCount + 1);
  inode res = setOne(v, 0, N - 1, kthZero);
  res = fillZeroes(res, zeroes, 0, N - 1, pos, kthZero - 1);
  return res;
}
bool compare(const inode &l, const inode &r, int len) {
  if (l->hash == r->hash) {
    return false;
  }
  if (len == 1) {
    return l->hash < r->hash;
  }
  if (l->r->hash == r->r->hash) {
    return compare(l->l, r->l, len >> 1);
  } else {
    return compare(l->r, r->r, len >> 1);
  }
}
long long sum;
const long long mod = 1000000007;
const bool debug = false;
void traverse(inode v, int tl, int tr) {
  if (tl == tr) {
    if (debug) cout << v->hash;
    sum = sum * 2 + v->hash;
    if (sum >= mod) {
      sum -= mod;
    }
    return;
  }
  int tm = (tl + tr) >> 1;
  traverse(v->r, tm + 1, tr);
  traverse(v->l, tl, tm);
}
struct iNumber {
  inode first;
  iNumber(inode z = zeroes) { first = z; }
  iNumber operator+(const int &r) const { return iNumber(add(first, r)); }
  bool operator<(const iNumber &r) const { return compare(first, r.first, N); }
  bool operator==(const iNumber &r) const {
    return !compare(first, r.first, N) && !compare(r.first, first, N);
  }
  long long value() const {
    sum = 0;
    traverse(first, 0, N - 1);
    if (debug) cout << endl;
    return sum;
  }
};
void initZEROandONE() {
  ONE = inode(new node());
  ONE->hash = 1;
  ONE->pw = 3;
  ONE->zeroCount = 0;
  ZERO = inode(new node());
  ZERO->hash = 0;
  ZERO->pw = 3;
  ZERO->zeroCount = 1;
  zeroes = build(0, N - 1, 0);
  ones = build(0, N - 1, 1);
}
int main() {
  initZEROandONE();
  int n, m;
  scanf("%d%d", &n, &m);
  iNumber infinity(ones);
  iNumber zero(zeroes);
  vector<iNumber> distance(n, infinity);
  vector<pair<int, int> > edges[n];
  for (int i = 0; i < m; ++i) {
    int a, b, len;
    scanf("%d%d%d", &a, &b, &len);
    --a, --b;
    edges[a].push_back(make_pair(b, len));
    edges[b].push_back(make_pair(a, len));
  }
  int s, t;
  scanf("%d%d", &s, &t);
  --s, --t;
  distance[s] = zero;
  set<pair<iNumber, int> > q;
  q.insert(make_pair(distance[s], s));
  vector<int> parent(n, -1);
  while (!q.empty()) {
    int v = q.begin()->second;
    q.erase(q.begin());
    for (auto edge : edges[v]) {
      int to = edge.first;
      int len = edge.second;
      iNumber newDistance = distance[v] + len;
      if (newDistance < distance[to]) {
        q.erase(make_pair(distance[to], to));
        distance[to] = newDistance;
        q.insert(make_pair(distance[to], to));
        parent[to] = v;
      }
    }
  }
  if (distance[t] == infinity) {
    printf("-1\n");
    return 0;
  }
  printf("%lld\n", distance[t].value());
  vector<int> path;
  while (t != -1) {
    path.push_back(t);
    t = parent[t];
  }
  reverse(path.begin(), path.end());
  printf("%d\n", path.size());
  for (int i = 0; i < (int)path.size(); ++i) {
    if (i) printf(" ");
    printf("%d", path[i] + 1);
  }
  printf("\n");
  return 0;
}
