#include "bits/stdc++.h"
#include <cassert>
#include <climits>
#include <functional>
#include <queue>
#include <vector>
using namespace std;
#define pii pair<int, int>
#define vpii vector<pii>
#define vvpii vector<vpii>
#define pii pair<int, int>
#define vi vector<int>
#define ll long long
const int MOD = ((int)(pow(10, 9) + 7));
struct node {
vi prev;
vi next;
ll d;
int paths1;
int paths2;
bool visited;
};
vvpii graph;
int N;
int M;
int baratno1, baratno2;
vector<node> nodes;
void dijkstra() {
nodes.assign(N, (node) {
.prev = vi(),
.next = vi(),
.d = LLONG_MAX,
.paths1 = 0,
.paths2 = 0,
.visited = false
});
priority_queue<pii, vpii, greater<>> pq;
pq.emplace(0, baratno1);
nodes[baratno1].d = 0;
while (!pq.empty()) {
int marked = pq.top().second;
int d = pq.top().first;
pq.pop();
if (d != nodes[marked].d)
continue;
for (pii n : graph[marked]) {
ll old = nodes[n.first].d;
ll newd = nodes[marked].d + n.second;
// cout << marked << " to " << n.first << " " << old << " " << newd << endl;
if (newd < old) {
nodes[n.first].d = newd;
pq.emplace(newd, n.first);
nodes[n.first].prev.clear();
nodes[n.first].prev.push_back(marked);
}
else if (newd == old) {
nodes[n.first].prev.push_back(marked);
}
}
}
}
void dfs_2_1(int x) {
node& ez = nodes[x];
int r = 0;
nodes[x].visited = true;
// cout << "in: " << x << "\n";
for (int next : ez.prev) {
node& ne = nodes[next];
ne.next.push_back(x);
// cout << "looking " << next << ": ";
if (next == baratno1) {
// cout << "next == baratno1\n";
r++;
r %= MOD;
}
else if (!ne.visited) {
// cout << "!ne.visited\n";
dfs_2_1(next);
r += nodes[next].paths1;
r %= MOD;
}
else if (ne.visited) {
// cout << "ne.visited\n";
r += nodes[next].paths1;
r %= MOD;
}
}
ez.paths1 = r;
}
void dfs_1_2(int x) {
node& ez = nodes[x];
int r = 0;
nodes[x].visited = false;
// cout << "in: " << x << "\n";
for (int next : ez.next) {
node& ne = nodes[next];
// cout << "looking " << next << ": ";
if (next == baratno2) {
// cout << "next == baratno2\n";
r++;
r %= MOD;
}
else if (ne.visited) {
// cout << "!ne.visited\n";
dfs_1_2(next);
r += nodes[next].paths2;
r %= MOD;
}
else if (!ne.visited) {
r += nodes[next].paths2;
r %= MOD;
// cout << "ne.visited\n";
}
}
ez.paths2 = r;
}
int diff = 0;
void dfs_end(int x) {
// 1_2
nodes[x].visited = true;
for (int next : nodes[x].next) {
if (nodes[next].visited)
continue;
int d_here = nodes[x].d;
int d_next = nodes[next].d;
int d_end = nodes[baratno2].d;
// cout << x << " " << next << " " << d_here << " " << d_next << "\n";
if (d_end % 2 == 0 && d_end / 2 == d_here) {
// meet here
diff += (nodes[x].paths1 * nodes[x].paths2) % MOD;
diff %= MOD;
}
else if (d_end / 2 >= d_here && d_end / 2 < d_next) {
// meet road
// cout << x << " " << next << "\n";
diff += (nodes[x].paths1 * nodes[next].paths2) % MOD;
diff %= MOD;
}
else {
// no meet
dfs_end(next);
}
}
}
int main() {
cin >> N >> M;
graph.assign(N, vector<pii>());
for (int i = 0; i < M; i++) {
int a, b, d;
cin >> a >> b >> d;
a--; b--;
graph[a].emplace_back(b, d);
graph[b].emplace_back(a, d);
}
cin >> baratno1 >> baratno2;
baratno1--; baratno2--;
dijkstra();
dfs_2_1(baratno2);
// cout << "-----------\n";
dfs_1_2(baratno1);
// for (int i = 0; i < N; i++) {
// auto n = nodes[i];
// cout << i << " " /*<< n.d << " "*/ << n.paths1 << " " << n.paths2 << /*" " << n.visited <<*/ "\n" << n.prev.size() << ": ";
// for (int i : n.prev)
// cout << i << " ";
// cout << "\n" << n.next.size() << ": ";
// for (int i : n.next)
// cout << i << " ";
// cout << "\n";
// }
dfs_end(baratno1);
// cout << diff << "\n";
cout << ((nodes[baratno1].paths2)*(nodes[baratno1].paths2) % MOD - diff) % MOD << endl;
}