#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<memory.h>
#include<algorithm>
#include<string.h>
#include<queue>

using namespace std;

    FILE *f, *g;
    int n,m;

struct cvor
{
    int id, dist;
    bool operator <(cvor x)const
    {
    return dist>x.dist;
    }

};

struct grana//za hip sa granama
{
        int poc, kraj;
        int vr;//koliki put do kraja daje
        int vr2;//koliki od drugog
        int min;//ovde pamtimo s1 ili s2, pamtimo onu cija je vrednost puta do vr

        bool operator <(grana g)const
        {
            return vr>g.vr;

        }

};

    priority_queue <cvor> a;
    priority_queue <cvor> a1;
    priority_queue <grana> b;

    int d1[10001]; int d2[10001];
    bool m1[10001]; bool m2[10001];
    vector<cvor> sus[10001];//tu se pamti id suseda, i rastojanje dist u ovom slucaju predstavlja medjusobno rastojanje

    int s1, s2;//dva cvora od kojih se ide
    cvor p, px;

    void dij1()
    {
        //mora se misliti na nedostizne!!!!!!!!
        for(int i = 0; i <= 10000; i++) d1[i] = -1;
        d1[s1] = 0;
        m1[s1] = 1;//posetili smo ga

        for(int i = 0; i < sus[s1].size(); i++)
        {
            p.dist = sus[s1][i].dist;
            p.id = sus[s1][i].id;
            a.push(p);
            d1[p.id] = p.dist;
        }


        while(!a.empty())
        {

            while(!a.empty()&&m1[a.top().id]==1)//dok je posecen
                a.pop();

            if(a.empty()) break;
            //inace imamo novi put

            p = a.top();
            a.pop();
            //sada relaksiramo preko njega
            m1[p.id] = 1;
            d1[p.id] = p.dist;

            //printf("%d %d\n", p.id, p.dist);

            for(int i = 0; i < sus[p.id].size(); i++)
            {
                if(!m1[sus[p.id][i].id])//ako nije do sada posecen definitivno
                if(d1[sus[p.id][i].id]==-1||(d1[sus[p.id][i].id]>sus[p.id][i].dist+d1[p.id]))
                {
                    d1[sus[p.id][i].id]=sus[p.id][i].dist+d1[p.id];
                    px.dist = d1[sus[p.id][i].id];
                    px.id = sus[p.id][i].id;
                    a.push(px);
                }
            }

        }

    }

    void dij2()
    {
               //mora se misliti na nedostizne!!!!!!!!
        for(int i = 0; i <= 10000; i++) d2[i] = -1;
        d2[s2] = 0;
        m2[s2] = 1;//posetili smo ga

        for(int i = 0; i < sus[s2].size(); i++)
        {
            p.dist = sus[s2][i].dist;
            p.id = sus[s2][i].id;
            a1.push(p);
            d2[p.id] = p.dist;
        }

        while(!a1.empty())
        {
            //printf("%d  ", a1.top().id);
            while(!a1.empty()&&m2[a1.top().id]==1)//dok je posecen
            a1.pop();

            if(a1.empty()) break;
            //inace imamo novi put

            p = a1.top();
            a1.pop();
            //sada relaksiramo preko njega
            m2[p.id] = 1;

           // printf("%d %d\n", p.id, p.dist);

            for(int i = 0; i < sus[p.id].size(); i++)
            {
                if(!m2[sus[p.id][i].id])//ako nije do sada posecen definitivno
                if(d2[sus[p.id][i].id]==-1||(d2[sus[p.id][i].id]>sus[p.id][i].dist+d2[p.id]))
                {
                    d2[sus[p.id][i].id]=sus[p.id][i].dist+d2[p.id];
                    px.dist = d2[sus[p.id][i].id];
                    px.id = sus[p.id][i].id;
                    a1.push(px);
                }
            }

        }
    }

    int dn1[10001];
    int dn2[10001];//za nove vrednosti dok vadimo grane iz hipa


    int main()
    {

        f = fopen("nishtel.in","r");
        g = fopen("nishtel.out","w");

        fscanf(f,"%d %d %d %d",&n,&m,&s1,&s2);



        int p1; cvor p;
        for(int i = 1; i <= m; i++)
        {
            fscanf(f,"%d%d%d",&p1,&p.id,&p.dist);
            sus[p1].push_back(p);
        }

     /*   for(int i = 1; i <= n; i++)
        {
                for(int j = 0; j < sus[i].size(); j++)
                {
                    printf("%d %d,", sus[i][j].id, sus[i][j].dist);
                }
                printf("\n");
        }   */


        dij1();
      //  for(int i = 1; i <= n; i++) printf("%d ",d1[i]);
        //printf("\n");


        dij2();
        //for(int i = 1; i <= n; i++) printf("%d ",d2[i]);
        //printf("\n");


        //printf("TAG!");

        //sada u hip dodamo samo one u dijkstra stablu.
        grana G; int minn;

        for(int i = 1; i <= n; i++)
        {
                for(int j = 0; j < sus[i].size(); j++)
                {
                            if((d1[i]!=-1&&d1[i]+sus[i][j].dist==d1[sus[i][j].id])||(d2[i]!=-1&&d2[i]+sus[i][j].dist==d2[sus[i][j].id]))//dakle, ako se do tog cvora moze doci, i ako je put to
                            {
                                G.poc = i; G.kraj = sus[i][j].id;
                                minn = 2000000100; int vr, vr2, min;//ovde pamtimo parametre

                                if(d1[sus[i][j].id]!=-1&&minn>d1[sus[i][j].id]) minn = s1;
                                if(d2[sus[i][j].id]!=-1&&minn>d2[sus[i][j].id]) minn = s2;
                                G.min = minn;
                                if(minn==s1) { vr = d1[sus[i][j].id]; vr2 = d2[sus[i][j].id]; }
                                else { vr2 = d1[sus[i][j].id]; vr = d2[sus[i][j].id];  }
                                G.vr = vr; G.vr2 = vr2;
                                b.push(G);

                            }
                }
        }

        int result = 0;//koliko mozemo izbaciti
        for(int i = 0; i <= 10000; i++) { dn1[i] = -1; dn2[i] = -1; }
        dn1[s1] = 0;
        dn2[s2] = 0;

        while(!b.empty())
        {
            G = b.top(); b.pop();
            bool potrebna = 0;

            if(G.min==s1)
            {
            if(dn1[G.kraj]==-1||(dn1[G.kraj]>G.vr)) { dn1[G.kraj] = G.vr; potrebna = 1; }

            if(G.vr2!=-1)//ako od drugog postoji put uopste preko nje do ovog
                if(dn2[G.kraj]==-1||dn2[G.kraj]>G.vr2) { dn2[G.kraj] = G.vr2; potrebna = 1; }
            }

            else if(G.min==s2)
            {
                if(dn2[G.kraj]==-1||(dn2[G.kraj]>G.vr)) { dn2[G.kraj] = G.vr; potrebna = 1; }

                if(G.vr2!=-1)//ako od drugog postoji put uopste preko nje do ovog
                    if(dn1[G.kraj]==-1||dn1[G.kraj]>G.vr2) { dn1[G.kraj] = G.vr2; potrebna = 1; }
            }
            if(!potrebna) result++;

        }

        fprintf(g,"%d\n", result);


        }


