const
   MaxN = 10010;
   MaxM = 100010;
   inf = 2000000000;


var
   inFile, outFile : Text;
   n, m, A, B, u, v, w, sol, i, heap_size : longint;
   a1, b1, w1, adj, weight : array[0..MaxM] of longint;
   d, dA, dB, p, deg : array[0..MaxN] of longint;
   h, posInHeap : array[0..MaxN] of longint;
   mark : array[0..MaxN] of boolean;


procedure Input;
var
   i, u, v, w: longint;

begin

   assign( inFile, 'nishtel.in' );
   reset( inFile );
   fillchar( deg, sizeof( deg ), 0 );

   readln( inFile, n, m, A, B );
   for i := 1 to m do begin
      readln( inFile, u, v, w );
      deg[ u ] := deg[ u ] + 1;
      a1[ i ] := u; b1[ i ] := v; w1[ i ] := w;
   end;

   close( inFile );

end;


procedure Output;
begin

   assign( outFile, 'nishtel.out');
   rewrite( outFile );
   writeln( outFile, sol);
   close( OutFile );

end;


(* simulacija liste preko counting sorta *)
procedure ListSimulation;
var
   i: longint;

begin

   p[0] := 0;
   for i := 1 to n do
      p[ i ] := p[ i - 1 ] + deg[ i - 1 ];

   for i := 1 to m do begin
      adj[ p[ a1[ i ] ] ] := b1[ i ];
      weight[ p[ a1[ i ] ] ] := w1[ i ];
      p[ a1[ i ] ] := p[ a1[ i ] ] + 1;
   end;

   for i := 1 to n do
      p[ i ] := p[ i - 1 ] + deg[ i - 1 ];

end;


procedure updateHeap( u, newVal : longint );
var
   f, s : longint;

begin

   d[ u ] := newVal;
   s := posInHeap[ u ];
   f := s div 2;

   while ((f <> 0) and (d[ h[ f ] ] > d[ u ])) do begin
      h[ s ] := h[ f ];
      posInHeap[ h[ f ] ] := s;
      s := f; f := s div 2;
   end;

   h[ s ] := u;
   posInHeap[ u ] := s;

end;


function extractMin: longint;
var
   f, s, u, min : longint;

begin

   min := h[ 1 ];
   u := h[ heap_size ];
   h[ 1 ] := u;
   heap_size := heap_size - 1;
   f := 1;
   s := 2 * f;
   if ((heap_size > s) and (d[ h[ s + 1 ] ] < d[ h[ s ] ])) then
      s := s + 1;

   while ((s <= heap_size) and (d[ u ] > d[ h[ s ] ])) do begin
      h[ f ] := h[ s ];
      posInHeap[ h[ s ] ] := f;
      f := s; s := 2 * f;
      if ((heap_size > s) and (d[ h[ s + 1 ] ] < d[ h[ s ] ])) then
         s := s + 1;
   end;

   h[ f ] := u;
   posInHeap[ u ] := f;
   extractMin := min;

end;


procedure Dijkstra( START : longint );
var
  u, v, w : longint;

begin

   for i := 1 to n do begin
      d[ i ] := inf;
      h[ i ] := i;
      posInHeap[ i ] := i;
   end;
   heap_size := n;
   updateHeap( START, 0 );

   while (heap_size > 0) do begin
      u := extractMin;
      for i := p[ u ] to p[ u ] + deg[ u ] - 1 do begin
         v := adj[ i ]; w := weight[ i ];
         if (d[ u ] + w < d[ v ]) then
            updateHeap( v, d[ u ] + w );
      end;
   end;

end;


begin

   Input;
   ListSimulation;

   Dijkstra( A );
   for i := 1 to n do dA[ i ] := d[ i ];
   Dijkstra( B );
   for i := 1 to n do dB[ i ] := d[ i ];

   sol := m - 2 * n + 2;
   for i := 1 to n do mark[ i ] := false;

   for u := 1 to n do
      for i := p[ u ] to p[ u ] + deg[ u ] - 1 do begin
         v := adj[ i ]; w := weight[ i ];
         if ((not mark[ v ]) and (dA[ v ] - dA[ u ] = w) and (dB[ v ] - dB[ u ] = w))
         then begin
            mark[ v ] := true;
            sol := sol + 1;
         end;
      end;

   Output;

end.