#include <bits/stdc++.h>
using namespace std;
const double PI = 3.14159265359;
void OLE(string s = "OLE") {
  cout << "OMG" << endl;
  exit(-1);
}
int maxTr = (int)1e6;
vector<unsigned long long> pows;
vector<int> pows2;
const int mod = (int)1e9 + 7;
void init() {
  pows.resize(maxTr + 1);
  pows[0] = 1;
  for (int i = 1; i < (int)pows.size(); ++i) pows[i] = 2011 * pows[i - 1];
  pows2.resize(pows.size());
  pows2[0] = 1;
  for (int i = 1; i < (int)pows2.size(); ++i) pows2[i] = 2 * pows2[i - 1] % mod;
}
struct Node {
  bool isPaint0, have0;
  unsigned long long hash;
  Node *l, *r;
  Node() {
    isPaint0 = have0 = true;
    hash = 0;
    l = r = 0;
  }
  Node* clone() {
    Node* c = new Node();
    c->isPaint0 = isPaint0;
    c->have0 = have0;
    c->hash = hash;
    c->l = l;
    c->r = r;
    return c;
  }
};
void tryPush(Node* t) {
  if (t == 0) return;
  if (t->l != 0) {
  }
  if (t->r != 0) {
  }
}
int get0(Node* t, int pos, int tl = 0, int tr = maxTr) {
  if (tr < pos || !t->have0) return -1;
  if (t->isPaint0) return max(tl, pos);
  if (tl == tr) return t->have0 ? tl : -1;
  int tm = (tl + tr) / 2;
  int res = get0(t->l, pos, tl, tm);
  if (res != -1) return res;
  res = get0(t->r, pos, tm + 1, tr);
  return res;
}
Node* set1(Node* t, int pos, int tl = 0, int tr = maxTr) {
  t = t->clone();
  if (tl == tr) {
    if (tl != pos) OLE();
    t->hash = pows[pos];
    t->have0 = false;
    t->isPaint0 = false;
  } else {
    if (t->isPaint0) {
      t->l = t->l->clone();
      t->r = t->r->clone();
      t->l->hash = 0;
      t->l->have0 = true;
      t->l->isPaint0 = true;
      t->r->hash = 0;
      t->r->have0 = true;
      t->r->isPaint0 = true;
    }
    int tm = (tl + tr) / 2;
    if (pos <= tm)
      t->l = set1(t->l, pos, tl, tm);
    else
      t->r = set1(t->r, pos, tm + 1, tr);
    t->hash = t->l->hash + t->r->hash;
    t->have0 = t->l->have0 || t->r->have0;
    t->isPaint0 = t->l->isPaint0 && t->r->isPaint0;
  }
  return t;
}
Node* paint0(Node* t, int l, int r, int tl = 0, int tr = maxTr) {
  if (l > r || t->isPaint0) return t;
  t = t->clone();
  if (tl == l && tr == r) {
    t->hash = 0;
    t->have0 = true;
    t->isPaint0 = true;
  } else {
    int tm = (tl + tr) / 2;
    t->l = paint0(t->l, l, min(r, tm), tl, tm);
    t->r = paint0(t->r, max(l, tm + 1), r, tm + 1, tr);
    t->hash = t->l->hash + t->r->hash;
    t->have0 = t->l->have0 || t->r->have0;
    t->isPaint0 = t->l->isPaint0 && t->r->isPaint0;
  }
  return t;
}
Node* addPow2(Node* t, int pos) {
  int ind = get0(t, pos);
  if (ind == -1) OLE();
  if (pos != ind) t = paint0(t, pos, ind - 1);
  t = set1(t, ind);
  return t;
}
Node* build(bool one, int tl = 0, int tr = maxTr) {
  Node* t = new Node();
  if (tl == tr) {
    if (one) t->hash = pows[tl];
    t->have0 = t->isPaint0 = !one;
    return t;
  }
  int tm = (tl + tr) / 2;
  t->l = build(one, tl, tm);
  t->r = build(one, tm + 1, tr);
  t->hash = t->l->hash + t->r->hash;
  t->have0 = t->l->have0 || t->r->have0;
  t->isPaint0 = t->l->isPaint0 && t->r->isPaint0;
  return t;
}
int cmpNumb(unsigned long long a, unsigned long long b) {
  if (a < b) return -1;
  if (a > b) return 1;
  return 0;
}
int cmp(const Node* a, const Node* b, int tl = 0, int tr = maxTr) {
  if (a == 0 && b == 0 || a->hash == b->hash) return 0;
  if (a->isPaint0 || b->isPaint0) return cmpNumb(a->hash, b->hash);
  int cmpR = cmp(a->r, b->r);
  if (cmpR != 0) return cmpR;
  return cmp(a->l, b->l);
}
int getMod(Node* t, int tl = 0, int tr = maxTr) {
  if (t == 0) return -1;
  if (t->isPaint0) return 0;
  if (tl == tr) return t->have0 ? 0 : pows2[tl];
  int tm = (tl + tr) / 2;
  return (getMod(t->l, tl, tm) + getMod(t->r, tm + 1, tr)) % mod;
}
int nextInt() {
  int n;
  scanf("%d", &n);
  return n;
}
struct Rib {
  int to, w;
  Rib(int _to, int _w) {
    to = _to;
    w = _w;
  }
};
int n, m;
vector<vector<Rib>> gr;
int begV, endV;
vector<Node*> dp;
vector<int> parent;
vector<int> path;
class qsdqdqdqs {
 public:
  bool operator()(const int& a, const int& b) const {
    int res = cmp(dp[a], dp[b]);
    return res == -1 || res == 0 && a < b;
  }
};
void rec(int v) {
  if (v == -1) return;
  rec(parent[v]);
  path.push_back(v);
}
void solve() {
  set<int, qsdqdqdqs> set;
  n = nextInt();
  m = nextInt();
  gr.assign(n + 1, vector<Rib>());
  for (int i = 0; i < m; ++i) {
    int a = nextInt();
    int b = nextInt();
    int w = nextInt();
    gr[a].push_back(Rib(b, w));
    gr[b].push_back(Rib(a, w));
  }
  begV = nextInt();
  endV = nextInt();
  dp.assign(n + 1, 0);
  dp[begV] = build(false);
  parent.assign(n + 1, -1);
  set.insert(begV);
  while (set.size()) {
    int v = *set.begin();
    set.erase(set.begin());
    for (int j = 0; j < (int)gr[v].size(); ++j) {
      Rib r = gr[v][j];
      Node* t = addPow2(dp[v], r.w);
      if (dp[r.to] == 0) {
        dp[r.to] = t;
        set.insert(r.to);
        parent[r.to] = v;
      } else if (cmp(dp[r.to], t) == 1) {
        set.erase(r.to);
        dp[r.to] = t;
        set.insert(r.to);
        parent[r.to] = v;
      }
    }
  }
  if (dp[endV] == 0)
    cout << "-1" << endl;
  else {
    cout << getMod(dp[endV]) << endl;
    rec(endV);
    cout << path.size() << endl;
    for (int i = 0; i < (int)path.size(); ++i) printf(" %d", path[i]);
    cout << endl;
  }
}
void deb() {
  {
    Node* t = build(false);
    for (int i = 1; i <= 100; ++i) {
      t = addPow2(t, 4);
      cout << getMod(t) << endl;
    }
  }
}
int main() {
  maxTr = (1 << 18) - 1;
  init();
  solve();
  return 0;
}
