use std::io::*;
use std::str::FromStr;
use std::collections::BinaryHeap;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

type Weight = i64;
#[allow(dead_code)]
#[derive(Clone, Debug, Eq, PartialEq)]
struct Edge {
    index: usize,
    src: usize,
    dest: usize,
    weight: Weight,
}
#[allow(dead_code)]
impl Edge {
    fn new(index: usize, src: usize, dest: usize, weight: Weight) -> Edge {
        Edge {
            index: index,
            src: src,
            dest: dest,
            weight: weight,
        }
    }
}
impl std::cmp::Ord for Edge {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        (self.weight, self.src, self.dest).cmp(&(other.weight, other.src, other.dest))
    }
}
impl std::cmp::PartialOrd for Edge {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}
type Edges = Vec<Edge>;
type Graph = Vec<Edges>;
#[allow(dead_code)]
fn graph_new(n: usize) -> Graph {
    vec![vec![]; n]
}
#[allow(dead_code)]
fn add_bi_edge(graph: &mut Graph, index: &mut usize, src: usize, dest: usize, weight: Weight) {
    graph[src].push(Edge::new(*index, src, dest, weight));
    graph[dest].push(Edge::new(*index, dest, src, weight));
    *index += 1;
}
#[allow(dead_code)]
fn add_uni_edge(graph: &mut Graph, index: &mut usize, src: usize, dest: usize, weight: Weight) {
    graph[src].push(Edge::new(*index, src, dest, weight));
    *index += 1;
}

const MOD: i64 = 1e+9 as i64 + 7;
#[allow(dead_code)]
fn dijkstra(g: &Graph, s: usize, t: usize) -> (Vec<i64>, Vec<i64>) {
    let n = g.len();
    let mut visit = vec![false; n];
    let mut dists = vec![Weight::max_value() / 10; n];
    let mut cnts = vec![0; n];
    let mut que = BinaryHeap::new();
    dists[s] = 0;
    cnts[s] = 1;
    que.push((0, s));
    while let Some((cost, from)) = que.pop() {
        let cost = -cost;
        if visit[from] { continue; }
        visit[from] = true;
        let cnt = cnts[from];
        if from == t { break; }
        for edge in g[from].iter() {
            let to = edge.dest;
            let ncost = cost + edge.weight;
            if ncost == dists[to] { cnts[to] = (cnts[to] + cnt) % MOD; }
            if visit[to] || ncost >= dists[to] { continue; }
            dists[to] = ncost;
            cnts[to] = cnt;
            que.push((-ncost, to));
        }
    }
    return (dists, cnts);
}
fn square(x: i64) -> i64 { x * x }

fn main() {
    let n: usize = read();
    let m: usize = read();
    let mut s: usize = read();
    let mut t: usize = read();
    s -= 1; t -= 1;
    let mut g = graph_new(n);
    let mut e = 0;
    for _ in 0..m {
        let mut f: usize = read();
        let mut t: usize = read();
        let d: i64 = read();
        f -= 1; t -= 1;
        add_bi_edge(&mut g, &mut e, f, t, d);
    }
    let mut distss = vec![vec![]; 2];
    let mut cntss = vec![vec![]; 2];
    for i in 0..2 {
        let (dists, cnts) = dijkstra(&g, [s, t][i], [t, s][i]);
        distss[i] = dists;
        cntss[i] = cnts;
    }
    // println!("{:?}", distss[0]);
    // println!("{:?}", cntss[0]);
    let mut ans = square(cntss[0][t]) % MOD;
    let dist = distss[0][t];
    for from in 0..n {
        if distss[0][from] == distss[1][from] {
            // println!("{} {} {}", from, cntss[0][from], cntss[1][from]);
            ans = (ans - square(cntss[0][from] * cntss[1][from] % MOD) % MOD + MOD) % MOD;
            continue;
        }
        for edge in g[from].iter() {
            let to = edge.dest;
            if distss[0][to] < distss[0][from] { continue; }
            if distss[0][from] + edge.weight + distss[1][to] != dist { continue; }
            if distss[0][from] * 2 < dist && dist < distss[0][to] * 2 {
                // println!("{} {} {} {}", from, to, cntss[0][from], cntss[1][to]);
                ans = (ans - square(cntss[0][from] * cntss[1][to] % MOD) % MOD + MOD) % MOD;
            }
        }
    }
    println!("{}", ans);
}

Measured memory_bytes: 35068