package main

import (
	"bufio"
	"container/heap"
	"fmt"
	"os"
	"strconv"
)

// Translate woqja125's code
// 2030742

type Item struct {
	vertex   int
	priority int
	index    int
}

type PriorityQueue []*Item

// For container/heap
func (pq PriorityQueue) Len() int { return len(pq) }
func (pq PriorityQueue) Less(i, j int) bool {
	return pq[i].priority < pq[j].priority
}
func (pq PriorityQueue) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
	pq[i].index = i
	pq[j].index = j
}
func (pq *PriorityQueue) Push(x interface{}) {
	n := len(*pq)
	item := x.(Item)
	item.index = n
	*pq = append(*pq, &item)
}
func (pq *PriorityQueue) Pop() interface{} {
	old := *pq
	n := len(old)
	item := old[n-1]
	item.index = -1 // for safety
	*pq = old[0 : n-1]
	return item
}

type edge struct {
	to   int
	cost int
}

const (
	MOD = 1000*1000*1000 + 7
)

var edges [][]edge

func dijkstra(startPos int, distance, count []int) {
	toVisit := make(PriorityQueue, 0, len(distance))

	for i := range distance {
		distance[i] = -1
	}
	count[startPos], distance[startPos] = 1, 0
	toVisit.Push(Item{vertex: startPos, priority: 0})
	heap.Init(&toVisit)
	for toVisit.Len() > 0 {
		point := heap.Pop(&toVisit).(*Item)
		if point.priority != distance[point.vertex] {
			continue
		}
		for _, e := range edges[point.vertex] {
			if distance[e.to] == -1 ||
				distance[e.to] > distance[point.vertex]+e.cost {
				distance[e.to] = distance[point.vertex] + e.cost
				count[e.to] = count[point.vertex]
				heap.Push(&toVisit, Item{vertex: e.to, priority: distance[e.to]})
			} else if distance[e.to] == distance[point.vertex]+e.cost {
				count[e.to] = (count[e.to] + count[point.vertex]) % MOD
			}
		}
	}
	return
}

func main() {
	in := IOInitialize()
	n, m := Int(in), Int(in)
	s, t := Int(in)-1, Int(in)-1
	edges = make([][]edge, n)
	for i := range edges {
		edges[i] = make([]edge, 0, 4)
	}

	for i := 0; i < m; i++ {
		u, v, d := Int(in)-1, Int(in)-1, Int(in)

		edges[u] = append(edges[u], edge{to: v, cost: d})
		edges[v] = append(edges[v], edge{to: u, cost: d})
	}
	distanceFromS := make([]int, n)
	distanceFromT := make([]int, n)
	CountFromS := make([]int, n)
	CountFromT := make([]int, n)

	dijkstra(s, distanceFromS, CountFromS)
	dijkstra(t, distanceFromT, CountFromT)

	c := make([]int, 0, (n/10)+10)
	OptLength, ans, S := distanceFromS[t], 0, 0
	for i := range distanceFromS {
		if distanceFromS[i] == distanceFromT[i] {
			c = append(c, CountFromS[i]*CountFromT[i]%MOD)
		}
		if distanceFromS[i]*2 >= OptLength {
			continue
		}
		for _, e := range edges[i] {
			if distanceFromS[i]+e.cost+distanceFromT[e.to] != OptLength {
				continue
			}
			if distanceFromT[e.to]*2 < OptLength {
				c = append(c, CountFromS[i]*CountFromT[e.to]%MOD)
			}
		}
	}
	for _, x := range c {
		S = (S + x) % MOD
	}
	for _, x := range c {
		ans = (ans + x*(S-x+MOD)) % MOD
	}

	fmt.Println(ans)
}

//////////
func IOInitialize() *bufio.Scanner {
	t := bufio.NewScanner(os.Stdin)
	t.Split(bufio.ScanWords)
	return t
}

func Int(s *bufio.Scanner) int {
	if !s.Scan() {
		panic("\t\tThere is a FALSE not to want.")
	}

	value, err := strconv.Atoi(s.Text())
	if err != nil {
		panic("\t\tError:Failed to convert text to int,")
	}
	return value
}


Measured memory_bytes: 33280