#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 1005
#define HUGE_NUM 9999999999999999


struct Edge{
	Edge(int arg_to,ll arg_cost,bool arg_is_magical){
		to = arg_to;
		cost = arg_cost;
		is_magical = arg_is_magical;
	}
	int to;
	ll cost;
	bool is_magical;
};

struct State{
	State(){
		node_id = 0;
		num_passed_magical = 0;
		sum_cost = 0;
	}
	State(int arg_node_id,int arg_num_passed_magical,ll arg_sum_cost){

		node_id = arg_node_id;
		num_passed_magical = arg_num_passed_magical;
		sum_cost = arg_sum_cost;
	}
	bool operator<(const struct State &arg) const{
		return sum_cost > arg.sum_cost;
	}
	int node_id,num_passed_magical;
	ll sum_cost;
};

int N,M,S_1,S_2,T;
int num_magical;
vector<Edge> G[NUM];
ll min_dist[105][NUM];

ll getNUM(char buf[20]){

	ll ret = 0;

	for(int i = 0; buf[i] != '\0'; i++){
		ret = 10*ret+(buf[i]-'0');
	}

	return ret;
}

double calc_len(ll slope_1,ll num_1,ll slope_2,ll num_2){

	return (double)(num_2-num_1)/(double)(slope_1-slope_2);
}

ll get_min_cost(int node,ll tmp_len){

	ll ret = HUGE_NUM;

	for(ll i = 0; i <= num_magical; i++){

		ret = min(ret,min_dist[i][node]+i*tmp_len);
	}
	return ret;
}

void dijkstra(int start){

	for(int i = 0; i <= num_magical; i++){
		for(int k = 0; k < N; k++){
			min_dist[i][k] = HUGE_NUM;
		}
	}

	priority_queue<State> Q;

	min_dist[0][start] = 0;
	Q.push(State(start,0,0));

	int next_node,next_num_pass;
	ll next_cost;
	State state;

	while(!Q.empty()){

		state = Q.top();
		Q.pop();

		if(state.sum_cost > min_dist[state.num_passed_magical][state.node_id]){
			continue;
		}

		for(int i = 0; i < G[state.node_id].size(); i++){

			next_node = G[state.node_id][i].to;
			next_cost = state.sum_cost+G[state.node_id][i].cost;
			next_num_pass = state.num_passed_magical;

			if(G[state.node_id][i].is_magical){
				next_num_pass++;
			}

			if(min_dist[next_num_pass][next_node] > next_cost){

				min_dist[next_num_pass][next_node] = next_cost;
				Q.push(State(next_node,next_num_pass,next_cost));
			}
		}
	}

}

void func(){

	for(int i = 0; i < N; i++){
		G[i].clear();
	}

	S_1--;
	S_2--;
	T--;

	char buf[20];

	int from,to;
	ll cost;
	num_magical = 0;

	for(int loop = 0; loop < M; loop++){

		scanf("%d %d %s",&from,&to,buf);
		from--;
		to--;

		if(buf[0] != 'x'){

			cost = getNUM(buf);
			G[from].push_back(Edge(to,cost,false));
			G[to].push_back(Edge(from,cost,false));

		}else{

			num_magical++;

			cost = 0;
			G[from].push_back(Edge(to,cost,true));
			G[to].push_back(Edge(from,cost,true));
		}
	}

	dijkstra(T);

	vector<ll> V; //長さの候補

	double len[3];

	for(ll i = 0; i <= num_magical; i++){
		for(ll k = 0; k <= num_magical; k++){

			if(k == i)continue;

			for(int a = 0; a < 3; a++)len[a] = 0;

			if(min_dist[i][S_1] != HUGE_NUM && min_dist[k][S_1] != HUGE_NUM)len[0] = calc_len(i,min_dist[i][S_1],k,min_dist[k][S_1]);
			if(min_dist[i][S_1] != HUGE_NUM && min_dist[k][S_2] != HUGE_NUM)len[1] = calc_len(i,min_dist[i][S_1],k,min_dist[k][S_2]);
			if(min_dist[i][S_2] != HUGE_NUM && min_dist[k][S_2] != HUGE_NUM)len[2] = calc_len(i,min_dist[i][S_2],k,min_dist[k][S_2]);

			for(ll diff = -1; diff <= 1; diff++){
				for(int a = 0; a < 3; a++){
					V.push_back((ll)len[a]+diff);
				}
			}
		}
	}

	sort(V.begin(),V.end());
	V.erase(unique(V.begin(),V.end()),V.end());

	ll ans = HUGE_NUM;

	if(min_dist[0][S_1] != HUGE_NUM && min_dist[0][S_2] != HUGE_NUM){
		ans = abs(min_dist[0][S_1]-min_dist[0][S_2]);
	}

	ll tmp_len;
	ll A_cost,B_cost;

	for(int i = 0; i < V.size(); i++){

		tmp_len = V[i];
		if(tmp_len < 0)continue;

		A_cost = get_min_cost(S_1,tmp_len);
		B_cost = get_min_cost(S_2,tmp_len);

		ans = min(ans,abs(A_cost-B_cost));
	}

	printf("%lld\n",ans);
}

int main(){

	while(true){
		scanf("%d %d %d %d %d",&N,&M,&S_1,&S_2,&T);
		if(N == 0 && M == 0 && S_1 == 0 && S_2 == 0 && T == 0)break;

		func();
	}

	return 0;
}



Measured memory_bytes: 5948