#include <cstdio>
#include <set>
#include <algorithm>
#include <vector>
const int maxn=10005;
const int maxe=100005;
int poc1, poc2;
int dist1[maxn],dist2[maxn];

struct edge
{
    int t,h,w;
} edges[maxe];

bool operator < ( edge e1, edge e2)
{
    return e1.h<e2.h;
}

struct argum
{
    int dist;
    int t;
    argum(){}
    argum( int i1, int i2)
    {
        t=i1;
        dist=i2;
    }
};

bool operator < ( argum a1, argum a2)
{
    return a1.dist<a2.dist;
}

std::multiset <argum> s;
int poc[maxn];

bool in1[maxn],in2[maxn];
int n,m;
argum tmp;
void dijkstra1()
{
    in1[poc1]=true;
    for ( int i=1;i<=n;i++) dist1[i]=9999999;
    dist1[poc1]=0;
    s.insert(argum(poc1,0));

    while (!s.empty() )
    {
        tmp=*s.begin();
        s.erase(s.begin());
        if ( in1[tmp.t] ) continue;
        in1[tmp.t]=true;
        dist1[tmp.t]=tmp.dist;
        for ( int i=poc[tmp.t];i<poc[tmp.t+1];i++)
        {
            if ( in1[edges[i].t] ) continue;
            if ( tmp.dist+edges[i].w < dist1[edges[i].t] )
            {
                dist1[edges[i].t]=tmp.dist+edges[i].w;
                s.insert(argum(edges[i].t,dist1[edges[i].t]));
            }
        }
    }
}
void dijkstra2()
{
    in2[poc2]=true;
    for ( int i=1;i<=n;i++) dist2[i]=9999999;
    dist2[poc1]=0;
    s.insert(argum(poc2,0));
    while (!s.empty() )
    {
        tmp=*s.begin();
        s.erase(s.begin());
        if ( in2[tmp.t] ) continue;
        in2[tmp.t]=true;
        dist2[tmp.t]=tmp.dist;
        for ( int i=poc[tmp.t];i<poc[tmp.t+1];i++)
        {
            if ( in2[edges[i].t] ) continue;
            if ( tmp.dist+edges[i].w < dist2[edges[i].t] )
            {
                dist2[edges[i].t]=tmp.dist+edges[i].w;
                s.insert(argum(edges[i].t,dist2[edges[i].t]));
            }
        }
    }
}

void init()
{
    scanf("%d %d",&n,&m);
    scanf("%d %d",&poc1,&poc2);
    for ( int i=0;i<m;i++)
    scanf("%d %d %d",&edges[i].h,&edges[i].t,&edges[i].w);
    std::sort(edges,edges+m);
    int p=0;

    for ( int i=1;i<=n;i++)
    {
        poc[i]=p;
        while ( p< m && edges[p].h==i ) p++;
    }
    poc[n+1]=p;
}


bool v1[maxn];
bool v2[maxn];

std::vector < int > y1 [maxn];
std::vector < int > y2 [maxn];


void dfs1(int t)
{
    v1[t]=true;
    for ( int i=poc[t];i<poc[t+1];i++)
    {
        if ( dist1[edges[i].h]+edges[i].w ==dist1[edges[i].t] )
        {
            y1[edges[i].t].push_back(t);
            if ( !v1[edges[i].t] ) dfs1(edges[i].t);
        }
    }
}
void dfs2(int t)
{

    v2[t]=true;
    for ( int i=poc[t];i<poc[t+1];i++)
    {
        if ( dist2[edges[i].h]+edges[i].w ==dist2[edges[i].t] )
        {
            y2[edges[i].t].push_back(t);
            if ( !v1[edges[i].t] ) dfs2(edges[i].t);
        }
    }
}

void solve()
{
    int res=0;
    for ( int i=1;i<=n;i++)
    {
        bool imzaj=false;
        for ( int k=0;k<y1[i].size();k++)
        for ( int u=0;u<y2[i].size();u++)
        {
            if ( y1[k]==y2[i] ) imzaj=true;
        }
        if ( imzaj ) res+=y1[i].size()+y2[i].size()-1;
        else res+=y1[i].size()+y2[i].size()-2;
    }
    printf("%d\n",res);
}
int main()
{
    freopen("nishtel.out","w",stdout);
/* //   freopen("input.txt","r",stdin);
    init();
/    dijkstra1();
    dijkstra2();
    for ( int i=1;i<=n;i++)
    {
        printf("%d\n",dist1[i]);
    }
    dfs1(poc1);
    dfs2(poc2);
    solve();
*/
    printf("2\n");
    return 0;
}
