#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<string>
#include<stack>
#include<cstdio>
#include<cmath>
#include<string.h>
using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> P;
typedef pair<ll,P> P1;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define rep(i,x) for(int i=0;i<x;i++)
#define rep1(i,x) for(int i=1;i<=x;i++)
#define rrep(i,x) for(int i=x-1;i>=0;i--)
#define rrep1(i,x) for(int i=x;i>0;i--)
#define sor(v) sort(v.begin(),v.end())
#define rev(s) reverse(s.begin(),s.end())
#define lb(vec,a) lower_bound(vec.begin(),vec.end(),a)
#define ub(vec,a) upper_bound(vec.begin(),vec.end(),a)
#define uniq(vec) vec.erase(unique(vec.begin(),vec.end()),vec.end())
#define mp1(a,b,c) P1(a,P(b,c))

const ll INF=1000000000000000000;
const int dir_4[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
const int dir_8[8][2]={{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};

int main(){
	while(1){
		ll n,m,s[2],t;
		ll a[2002],b[2002];
		ll w[2002];
		scanf("%lld%lld%lld%lld%lld",&n,&m,&s[0],&s[1],&t);
		if(n==0)return 0;
		rep(i,m){
			scanf("%lld%lld",&a[i],&b[i]);
			string in;
			cin >> in;
			if(in == "x")w[i] = INF;
			else {
				w[i] = 0;
				rep(j,in.size()){
					w[i] *= 10;
					w[i] += in[j]-'0';
				}
			}
		}
		
		vector<P> G[2002];
		rep(i,m){
			G[a[i]].pb(P(b[i],w[i]));
			G[b[i]].pb(P(a[i],w[i]));
		}
		
		static ll cost[1002][102];
		static bool used[1002][102];
		static priority_queue<P1,vector<P1>,greater<P1>> que;
		rep(i,1002)rep(j,102){
			cost[i][j] = INF;
			used[i][j] = false;
		}
		cost[t][0] = 0;
		que.push(mp1(0,t,0));
		while(!que.empty()){
			P1 p = que.top(); que.pop();
			if(used[p.sc.fr][p.sc.sc])continue;
			used[p.sc.fr][p.sc.sc] = true;
			rep(i,G[p.sc.fr].size()){
				P ed = G[p.sc.fr][i];
				if(ed.sc == INF){
					if(p.sc.sc < 100){
						if(cost[ed.fr][p.sc.sc+1] > p.fr){
							cost[ed.fr][p.sc.sc+1] = p.fr;
							que.push(mp1(cost[ed.fr][p.sc.sc+1],ed.fr,p.sc.sc+1));
						}
					}
				}
				else {
					if(cost[ed.fr][p.sc.sc] > p.fr+ed.sc){
						cost[ed.fr][p.sc.sc] = p.fr+ed.sc;
						que.push(mp1(cost[ed.fr][p.sc.sc],ed.fr,p.sc.sc));
					}
				}
			}
		}
		
		vector<P> vec[2];
		rep(i,2){
			rep1(j,100){
				cost[s[i]][j] = min ( cost[s[i]][j] , cost[s[i]][j-1] );
			}
			rrep(j,101){
				while(vec[i].size() >= 2){
					P p=vec[i][vec[i].size()-1];
					P q=vec[i][vec[i].size()-2];
					if((p.fr-q.fr)/(q.sc-p.sc) < (cost[s[i]][j]-p.fr)/(p.sc-j)){
						break;
					}
					else vec[i].pop_back();
				}
				vec[i].pb(P(cost[s[i]][j],j));
			}
		}
		
		vector<ll> x;
		x.pb(0);
		rep(i,2){
			for(int j = 0 ; j+1 < vec[i].size() ; j ++){
				ll x_ = (vec[i][j].fr-vec[i][j+1].fr)/(vec[i][j+1].sc-vec[i][j].sc);
				x.pb(x_);
				x.pb(x_+1);
			}
		}
		rep(i,101)rep(j,101){
			if(i==j)continue;
			if(i>j && cost[s[0]][i]<cost[s[1]][j]){
				ll x_ = (-cost[s[0]][i]+cost[s[1]][j])/(i-j);
				x.pb(x_);
				x.pb(x_+1);
			}
			if(i<j && cost[s[0]][i]>cost[s[1]][j]){
				ll x_ = (cost[s[0]][i]-cost[s[1]][j])/(j-i);
				x.pb(x_);
				x.pb(x_+1);
			}
		}
		
		/*rep(i,4){
			printf("%lld %lld\n",cost[s[0]][i],cost[s[1]][i]);
		}*/
		
		ll ret = INF;
		rep(i,x.size()){
			ll dist[2] = {INF,INF};
			rep(j,2){
				rep(k,101){
					dist[j] = min ( dist[j] , k*x[i]+cost[s[j]][k] );
				}
			}
			//cout << dist[0] << dist[1] << endl;
			ret = min ( ret , abs(dist[0]-dist[1]) );
		}
		cout << ret << endl;
	}
}

Measured memory_bytes: 5704