#![allow(unused_imports)]
use std::io::*;
use std::fmt::*;
use std::str::*;
use std::cmp::*;
use std::collections::*;

pub trait InputValue {
    fn parse(s: &str) -> Self;
}

pub fn read<T: InputValue>() -> T {
    let mut buf = String::new();
    let _ = stdin().read_line(&mut buf);
    T::parse(&buf.trim())
}

pub fn readn<T: InputValue>(n: usize) -> Vec<T> {
    let mut vec = vec![];
    for _ in 0..n {
        vec.push(read());
    }
    vec
}

pub fn readnc<T: InputValue>() -> Vec<T> {
    let mut vec = vec![];
    let line: String = read();
    for token in line.split_whitespace() {
        vec.push(T::parse(token));
    }
    vec
}

macro_rules! parse_single_value {
    ($($t:ty),*) => {
        $(
            impl InputValue for $t {
                fn parse(s: &str) -> $t { s.parse().unwrap() }
            }
        )*
	}
}
parse_single_value!(i32, i64, f32, f64, u32, u64, usize, String);

macro_rules! parse_tuple {
	($($t:ident),*) => {
		impl<$($t),*> InputValue for ($($t),*) where $($t: InputValue),* {
			fn parse(s: &str) -> ($($t),*) {
				let mut tokens = s.split_whitespace();
				let t = ($($t::parse(tokens.next().unwrap())),*);
				t
			}
		}
	}
}
parse_tuple!(A, B);
parse_tuple!(A, B, C);
parse_tuple!(A, B, C, D);
parse_tuple!(A, B, C, D, E);

// ===

type Graph = Vec<Vec<(usize, i64, bool)>>;

const INF: i64 = 1e18 as i64;
const MOD: i64 = 1_000_000_007;

fn main() {
    let (n, m): (usize, usize) = read();
    let (s, t): (usize, usize) = read();
    let (s, t) = (s-1, t-1);


    let mut edges = vec![];
    let mut graph: Graph = vec![vec![]; n];
    for _ in 0..m {
        let (u, v, d): (usize, usize, i64) = read();
        graph[u-1].push((v-1, d, true));
        graph[v-1].push((u-1, d, true));
        edges.push((u-1, v-1));
    }

    let (dist_from_s, _) = dist_from(&graph, s);
    let (dist_from_t, _) = dist_from(&graph, t);

    for i in 0..n {
        let deg = graph[i].len();
        for j in 0..deg {
            let e = graph[i][j];
            if !valid(i, e.0, e.1, s, t, &dist_from_s, &dist_from_t) {
                graph[i][j].2 = false;
            }
        }
    }

    let (dist_from_s, ways_from_s) = dist_from(&graph, s);
    let (dist_from_t, ways_from_t) = dist_from(&graph, t);
    let mut total = ways_from_s[t] * ways_from_s[t] % MOD;
    for i in 0..n {
        if dist_from_s[i] == dist_from_t[i] {
            let ws = ways_from_s[i];
            let wt = ways_from_t[i];
            total += MOD - ws * ws % MOD * wt % MOD * wt % MOD;
            total %= MOD;
        }
    }
    for i in 0..n {
        let deg = graph[i].len();
        for j in 0..deg {
            if !graph[i][j].2 || dist_from_s[i] > dist_from_s[graph[i][j].0] {
                continue;
            }
            let (u, v, d) = (i, graph[i][j].0, graph[i][j].1);
            if max(dist_from_s[u], dist_from_t[v]) < min(dist_from_s[u] + d, dist_from_t[v] + d) {
                let ws = ways_from_s[u];
                let wt = ways_from_t[v];
                total += MOD - ws * ws % MOD * wt % MOD * wt % MOD;
                total %= MOD;
            }
        }
    }

    println!("{}", total % MOD);
}

fn valid(u: usize, v: usize, d: i64, s: usize, t: usize, dist_s: &Vec<i64>, dist_t: &Vec<i64>) -> bool {
    if dist_s[v] < dist_s[u] {
        return valid(v, u, d, s, t, dist_s, dist_t);
    }
    let total = dist_s[t];
    dist_s[u] + d + dist_t[v] == total && dist_s[u] + d == dist_s[v] && dist_t[v] + d == dist_t[u]
}

fn dist_from(graph: &Graph, from: usize) -> (Vec<i64>, Vec<i64>) {
    let n = graph.len();
    let mut ret = vec![INF; n];
    let mut ways = vec![0; n];
    ret[from] = 0;
    ways[from] = 1;

    let mut heap = BinaryHeap::new();
    heap.push((0, from));

    while heap.len() >= 1 {
        let (dist, idx) = heap.pop().unwrap();
        let dist = -dist;
        if ret[idx] < dist {
            continue;
        }

        let wa = ways[idx];
        for &(to, d, valid) in &graph[idx] {
            if ret[to] > dist + d {
                ret[to] = dist + d;
                ways[to] = wa;
                heap.push((-ret[to], to))
            } else if ret[to] == dist + d {
                ways[to] += wa;
                ways[to] %= MOD;
            }
        }
    }
    (ret, ways)
}

Measured memory_bytes: 38308