// Slower C++ solution:
#include<cstdio>

#include<cstring>

#include<algorithm>

#include<vector>

#include<iostream>

#include<queue>

#include<cmath>



using namespace std;



typedef long long ll;



const int maxn = 1005;

const int maxl = 105;

const ll inf = 1ll<<55;

const double eps = 1e-8;



struct edge

{

	int to,val,mag;

	edge(int a,int b,int c):to(a),val(b),mag(c){}

};



struct node

{

	int to,mag;

	ll len;

	node(int a,int b,ll c):to(a),mag(b),len(c){}

	bool operator<(const node& a)const

	{

		return len > a.len;

	}

};



struct point

{

	double xi,lef,di;

	point(){}

	point(double a,double b,double c):xi(a),lef(b),di(c){}

};



vector<edge> v[maxn];

bool vis[maxn][maxl];

ll dis[maxn][maxl];



int n,s1,s2,tt,sp;

struct line

{

	point s[maxl];int top;

	void build()

	{

		top = 0;

		for(int i=sp;i>=0;i--)

		{

			if(dis[tt][i]==inf)

				continue;

			while(top&&i*s[top-1].lef+dis[tt][i]<=eps+s[top-1].xi*s[top-1].lef+s[top-1].di)

				top--;

			s[top] = point(i,top?(dis[tt][i]-s[top-1].di)/(s[top-1].xi-i):0,dis[tt][i]);

			top++;

		}

	}

}p1,p2;



int f1,f2;



double f(double x)

{

	return fabs(p1.s[f1].xi*x+p1.s[f1].di-p2.s[f2].xi*x-p2.s[f2].di);

}

double cal(double pl,double pr)

{

	if(abs((p2.s[f2].xi-p1.s[f1].xi))<=eps)

		return   fabs(p1.s[f1].di-p2.s[f2].di);

	pl = ceil(pl);pr = floor(pr);

	double jiao = (p1.s[f1].di-p2.s[f2].di)/(p2.s[f2].xi-p1.s[f1].xi);

	if(jiao>pr+eps)

		return f(pr);

	if(jiao<pl-eps)

		return f(pl);

	return min(f(ceil(jiao)),f(floor(jiao)));

}

double sol()

{

	double res = inf;

	vector<double> bl,v1,v2;

	for(int i=0;i<p1.top;i++)

	{

		v1.push_back(p1.s[i].lef);

		bl.push_back(p1.s[i].lef);

	}

	for(int i=0;i<p2.top;i++)

	{

		v2.push_back(p2.s[i].lef);

		bl.push_back(p2.s[i].lef);

	}

	sort(bl.begin(),bl.end());bl.push_back(1ll<<42);

	for(int i=2;i<bl.size();i++)

	{

		double va = bl[i];

		f1 = lower_bound(v1.begin(),v1.end(),va-eps)-v1.begin()-1;

		f2 = lower_bound(v2.begin(),v2.end(),va-eps)-v2.begin()-1;

		res = min(cal(bl[i-1],va),res);

	}

	return res;

}

void dij(int s)

{

	priority_queue<node> q;

	memset(vis,0,sizeof(vis));

	for(int i=1;i<=n;i++)

		fill(dis[i],dis[i]+sp+1,inf);

	dis[s][0] = 0;q.push(node(s,0,0));

	while(!q.empty())

	{

		node t = q.top();q.pop();

		if(vis[t.to][t.mag])

			continue;

		vis[t.to][t.mag] = 1;

		for(int i=0;i<v[t.to].size();i++)

		{

			int toit = v[t.to][i].to;

			if(dis[toit][t.mag+v[t.to][i].mag]>dis[t.to][t.mag]+v[t.to][i].val)

			{

				dis[toit][t.mag+v[t.to][i].mag]=dis[t.to][t.mag]+v[t.to][i].val;

				q.push(node(toit,t.mag+v[t.to][i].mag,dis[toit][t.mag+v[t.to][i].mag]));

			}

		}

	}

}

int main()

{

	int m,a,b;char s[20];

	while(scanf("%d%d%d%d%d",&n,&m,&s1,&s2,&tt)&&n)

	{

		sp = 0;

		for(int i=1;i<=n;i++)

			v[i].clear();

		for(int i=0;i<m;i++)

		{

			scanf("%d%d%s",&a,&b,s);

			if(s[0]=='x')

			{

				sp++;

				v[a].push_back(edge(b,0,1));

				v[b].push_back(edge(a,0,1));

			}

			else

			{

				int val = atoi(s);

				v[a].push_back(edge(b,val,0));

				v[b].push_back(edge(a,val,0));

			}

		}

		dij(s1);p1.build();

		dij(s2);p2.build();

		printf("%.0f\n",sol());

	}

}

// Faster C++ solution for the same problem (measured speedup: 1.1439739136263487x):
#include <bits/stdc++.h>

using namespace std;

const long long INF=1LL<<60;

const int MAXN=1005;

int n, m, S1, S2, T;

char s[100];

struct edge{

    int to;

    long long w;

    bool type;

    edge(int to=0, long long w=0, bool type=false):to(to),w(w),type(type) {}

};

vector<edge> G[MAXN];

long long dist[MAXN][MAXN];

priority_queue< pair<long long, pair<int, int> > > q;

pair<long long, pair<int, int> > now;

vector<long long> ans;

long long cross(long long a1, long long b1, long long a2, long long b2){

    if(a1==INF||a2==INF) return 0;

    return floor((a1-a2+1.0)/(b2-b1));

}

long long calc(long long dp[MAXN], int k, long long x){

    long long ret=INF;

    for(int i=0; i<=k; i++){

        ret=min(ret,dp[i]+x*i);

    }

    return ret;

}

int main(){

    while(~scanf("%d%d%d%d%d",&n,&m,&S1,&S2,&T)&&n){

        for(int i=1; i<=n; i++){

            G[i].clear();

        }

        int k=0;

        for(int i=0, x, y, z; i<m; i++){

            scanf("%d%d%s",&x,&y,s);

            if(s[0]=='x'){

                G[x].push_back(edge(y,0,1));

                G[y].push_back(edge(x,0,1));

                k++;

            }

            else{

                sscanf(s,"%d",&z);

                G[x].push_back(edge(y,z,0));

                G[y].push_back(edge(x,z,0));

            }

        }

        for(int i=1; i<=n; i++){

            for(int j=0; j<=k; j++){

                dist[i][j]=INF;

            }

        }

        dist[T][0]=0;

        while(!q.empty()) q.pop();

        q.push(make_pair(0LL,make_pair(T,0)));

        while(!q.empty()){

            now=q.top(); q.pop();

            int u=now.second.first, cnt=now.second.second;

            long long d=dist[u][cnt];

            if(-now.first>d) continue;

            for(auto p: G[u]){

                int ncnt=cnt+p.type, nidx=p.to;

                long long ndist=d+p.w;

                if(ncnt<=k&&ndist<dist[nidx][ncnt]){

                    dist[nidx][ncnt]=ndist;

                    q.push(make_pair(-ndist,make_pair(nidx,ncnt)));

                }

            }

        }

        ans.clear();

        ans.push_back(0LL);

        for(int i=0; i<=k; i++){

            for(int j=0; j<=k; j++) if(i!=j){

                long long x1, x2, x3;

                x1=cross(dist[S1][i],i,dist[S2][j],j);

                x2=cross(dist[S1][i],i,dist[S1][j],j);

                x3=cross(dist[S2][i],i,dist[S2][j],j);

                for(int d=-1; d<=1; d++){

                    ans.push_back(x1+d);

                    ans.push_back(x2+d);

                    ans.push_back(x3+d);

                }

            }

        }

        sort(ans.begin(),ans.end());

        ans.erase(unique(ans.begin(),ans.end()),ans.end());

        long long ret=INF;

        for(auto p: ans){

            if(p>=0){

                ret=min(ret,abs(calc(dist[S1],k,p)-calc(dist[S2],k,p)));

            }

        }

        printf("%lld\n",ret);

    }

    return 0;

}