use std::collections::BinaryHeap;

const MOD: usize = 1e9 as usize + 7;
const INF: i64 = 1 << 60;
fn main() {
    let (r, w) = (std::io::stdin(), std::io::stdout());
    let mut sc = IO::new(r.lock(), w.lock());
    let n: usize = sc.read();
    let m: usize = sc.read();
    let s = sc.read::<usize>() - 1;
    let t = sc.read::<usize>() - 1;

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

    let (dist_s, c_s) = dijkstra(s, &graph);
    let (dist_t, c_t) = dijkstra(t, &graph);

    let dist = dist_s[t];
    let mut sum = 0;
    for from in 0..n {
        for &(to, cost) in graph[from].iter() {
            if dist_s[from] + cost == dist_s[to]
                && dist_s[from] + cost + dist_t[to] == dist
                && dist_s[from] * 2 < dist
                && dist < dist_s[to] * 2
            {
                let p = (c_s[from] * c_t[to]) % MOD;
                sum += (p * p) % MOD;
                sum %= MOD;
            }
        }

        if dist_s[from] == dist_t[from] && dist_s[from] * 2 == dist {
            let p = (c_s[from] * c_t[from]) % MOD;
            sum += (p * p) % MOD;
            sum %= MOD;
        }
    }

    let ans = (c_s[t] * c_t[s]) % MOD + MOD - sum;
    println!("{}", ans % MOD);
}

fn dijkstra(start: usize, graph: &Vec<Vec<(usize, i64)>>) -> (Vec<i64>, Vec<usize>) {
    let mut dist = vec![INF; graph.len()];
    dist[start] = 0;

    let mut c = vec![0; graph.len()];
    c[start] = 1;

    let mut vis = vec![false; graph.len()];

    let mut heap = BinaryHeap::new();
    heap.push((-dist[start], start));
    while let Some((_, v)) = heap.pop() {
        if vis[v] {
            continue;
        }
        vis[v] = true;

        for &(next, cost) in graph[v].iter() {
            if dist[next] > dist[v] + cost {
                dist[next] = dist[v] + cost;
                c[next] = c[v];
                heap.push((-dist[next], next));
            } else if dist[next] == dist[v] + cost {
                c[next] += c[v];
                c[next] %= MOD;
            }
        }
    }
    (dist, c)
}

pub struct IO<R, W: std::io::Write>(R, std::io::BufWriter<W>);

impl<R: std::io::Read, W: std::io::Write> IO<R, W> {
    pub fn new(r: R, w: W) -> IO<R, W> {
        IO(r, std::io::BufWriter::new(w))
    }
    pub fn write<S: std::ops::Deref<Target = str>>(&mut self, s: S) {
        use std::io::Write;
        self.1.write(s.as_bytes()).unwrap();
    }
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .0
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r' || b == b'\t')
            .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r' && b != b'\t')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}


Measured memory_bytes: 24956