#include <bits/stdc++.h>
using namespace std;
using ull = unsigned long long;
const int kMod = 1e9 + 7;
mt19937_64 rng(time(0));
struct SegTree {
  struct Node {
    ull dp = 0;
    int l = 0, r = 0;
    ull hash = 0;
  };
  int n;
  vector<Node> T;
  vector<ull> rnd;
  SegTree(int n) : n(n), T(1), rnd(n) {
    for (int i = 0; i < n; ++i) rnd[i] = rng();
  }
  pair<int, int> add(int node, int b, int e, int pos) {
    if (e <= pos) return {node, 0};
    if (b == pos && T[node].dp + 1 == 0) return {0, 1};
    T.emplace_back();
    int ret = T.size() - 1;
    if (e - b == 64) {
      T[ret].dp = T[node].dp;
      T[ret].dp += (1ULL << (pos - b));
      int state = 1 + (T[ret].dp > T[node].dp);
      for (int i = b; i < e; ++i)
        if (T[ret].dp & (1ULL << (i - b))) T[ret].hash += rnd[i];
      return {ret, state};
    }
    int state;
    int l = T[node].l, r = T[node].r;
    int m = (b + e) / 2;
    tie(l, state) = add(l, b, m, pos);
    if (state == 0)
      tie(r, state) = add(r, m, e, pos);
    else if (state == 1)
      tie(r, state) = add(r, m, e, m);
    T[ret].l = l;
    T[ret].r = r;
    T[ret].hash = T[l].hash + T[r].hash;
    T[ret].dp = min(T[l].dp, T[r].dp);
    return {ret, state};
  }
  int Add(int node, int val) {
    auto [ret, state] = add(node, 0, n, val);
    assert(state == 2);
    return ret;
  }
  int compare(int x, int y, int b, int e) {
    if (T[x].hash == T[y].hash) return 0;
    if (e - b == 64) return T[x].dp < T[y].dp ? -1 : 1;
    int m = (b + e) / 2;
    int ret = compare(T[x].r, T[y].r, m, e);
    if (ret) return ret;
    return compare(T[x].l, T[y].l, b, m);
  }
  int Compare(int a, int b) { return compare(a, b, 0, n); }
  void get(int node, int b, int e, int& ans) {
    if (e - b == 64) {
      for (int i = b; i < e; ++i) ans = (ans + ans) % kMod;
      ans = (ans + T[node].dp % kMod) % kMod;
    } else {
      int m = (b + e) / 2;
      get(T[node].r, m, e, ans);
      get(T[node].l, b, m, ans);
    }
  }
  int Get(int node) {
    int ans = 0;
    get(node, 0, n, ans);
    return ans;
  }
};
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<vector<pair<int, int>>> graph(n);
  for (int i = 0; i < m; ++i) {
    int a, b, c;
    cin >> a >> b >> c;
    --a;
    --b;
    graph[a].emplace_back(c, b);
    graph[b].emplace_back(c, a);
  }
  SegTree st(1 << 17);
  int s, t;
  cin >> s >> t;
  --s;
  --t;
  auto cmp = [&](pair<int, int> a, pair<int, int> b) {
    return st.Compare(a.first, b.first) == 1;
  };
  priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> pq(cmp);
  vector<int> dist(n, -1), parent(n, -1), vis(n, false);
  dist[s] = 0;
  pq.emplace(0, s);
  while (pq.size()) {
    auto [d, node] = pq.top();
    pq.pop();
    if (d != dist[node]) continue;
    if (node == t) break;
    vis[node] = true;
    for (auto [cost, vec] : graph[node]) {
      if (vis[vec]) continue;
      int nd = st.Add(d, cost);
      if (dist[vec] == -1 || st.Compare(nd, dist[vec]) == -1) {
        dist[vec] = nd;
        parent[vec] = node;
        pq.emplace(nd, vec);
      }
    }
  }
  if (dist[t] == -1) {
    cout << -1 << '\n';
  } else {
    vector<int> trace;
    for (int node = t; node != -1; node = parent[node]) trace.push_back(node);
    reverse(trace.begin(), trace.end());
    cout << st.Get(dist[t]) << endl;
    cout << trace.size() << endl;
    for (auto x : trace) cout << x + 1 << " ";
    cout << endl;
  }
  return 0;
}
