#include <bits/stdc++.h>

using namespace std;

#define int long long
#define all(v) (v).begin(), (v).end()
#define resz(v, ...) (v).clear(), (v).resize(__VA_ARGS__)
#define reps(i, m, n) for(int i = (int)(m); i < (int)(n); i++)
#define rep(i, n) reps(i, 0, n)

template<class T1, class T2> void chmin(T1 &a, T2 b){if(a>b)a=b;}
template<class T1, class T2> void chmax(T1 &a, T2 b){if(a<b)a=b;}

typedef pair<int, int> Pi;
typedef tuple<int, int, int> Ti;
typedef vector<int> vint;

const int inf = 1LL << 55;
const int mod = 1e9 + 7;

struct edge {
  int to, cost;
  edge(){}
  edge(int to, int cost):to(to), cost(cost){}
};

int N, M, S1, S2, T;
vector< vector<edge> > rgraph;

struct State {
  int now, cost, magic;
  State(){}
  State(int now, int cost, int magic):now(now), cost(cost), magic(magic){}
  bool operator < (const State &s) const {
    return cost > s.cost;
  }
};

vector<vint> mincost;

void rdijkstra() {
  resz(mincost, 101, vint(N, inf));
  priority_queue<State> que;
  mincost[0][T] = 0;
  que.emplace(T, 0, 0);
  while(!que.empty()) {
    State s = que.top(); que.pop();
    if(mincost[s.magic][s.now] < s.cost) continue;
    for(edge& e : rgraph[s.now]) {
      if(e.cost >= 0) {
	if(e.cost + s.cost < mincost[s.magic][e.to]) {
	  mincost[s.magic][e.to] = e.cost + s.cost;
	  que.emplace(e.to, e.cost + s.cost, s.magic);
	}
      } else if(s.magic+1 < 101) {
	if(s.cost < mincost[s.magic+1][e.to]) {
	  mincost[s.magic+1][e.to] = s.cost;
	  que.emplace(e.to, s.cost, s.magic+1);
	}
      }
    }
  }
}

signed main()
{
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);

  while(cin >> N >> M >> S1 >> S2 >> T, N+M+S1+S2+T) {
    S1--, S2--, T--;
    resz(rgraph, N);
    rep(i, M) {
      int s, t; string ws;
      cin >> s >> t >> ws;
      s--, t--;
      if(ws == "x") {
	rgraph[s].emplace_back(t, -1);
	rgraph[t].emplace_back(s, -1);
      } else {
	int w = stoi(ws);
	rgraph[s].emplace_back(t, w);
	rgraph[t].emplace_back(s, w);
      }
    }
    rdijkstra();

    vector<double> crossX;
    crossX.emplace_back(0);
    rep(i, 101) rep(j, 101) {
      if(i == j) continue;
      if(mincost[i][S1] == inf || mincost[j][S2] == inf) continue;
      crossX.emplace_back(((double)mincost[j][S2]-mincost[i][S1])/(i-j));
      crossX.emplace_back(((double)mincost[i][S1]-mincost[j][S2])/(j-i));
      crossX.emplace_back(((double)mincost[j][S1]-mincost[i][S1])/(i-j));
      crossX.emplace_back(((double)mincost[i][S2]-mincost[j][S2])/(j-i));
    }

    int ans = inf;
    for(double x : crossX) {
      int ceil_x = ceil(x);
      int floor_x = floor(x);
      if(ceil_x >= 0) {
	int c = inf, d = inf;
	rep(i, 101) {
	  if(mincost[i][S1] != inf) chmin(c, mincost[i][S1]+ceil_x*i);
	  if(mincost[i][S2] != inf) chmin(d, mincost[i][S2]+ceil_x*i);
	}
	if(c != inf && d != inf) chmin(ans, llabs(c - d));
      }
      if(floor_x >= 0) {
	int c = inf, d = inf;
	rep(i, 101) {
	  if(mincost[i][S1] != inf) chmin(c, mincost[i][S1]+floor_x*i);
	  if(mincost[i][S2] != inf) chmin(d, mincost[i][S2]+floor_x*i);
	}
	if(c != inf && d != inf) chmin(ans, llabs(c - d));
      }
    }
    assert(ans != inf);
    cout << ans << endl;
  }

  return 0;
}

Measured memory_bytes: 6736