Problem:
Problem Statement
A magician lives in a country which consists of
N
islands and
M
bridges. 
Some of the bridges are magical bridges, which are created by the magician.
Her magic can change all the lengths of the magical bridges to the same non-negative integer simultaneously.
This country has a famous 2-player race game.
Player 1 starts from island
S_1
and Player 2 starts from island
S_2
. 
A player who reached the island
T
first is a winner.
Since the magician loves to watch this game, she decided to make the game most exiting by changing the length of the magical bridges
so that the difference between the shortest-path distance from
S_1
to
T
and the shortest-path distance from
S_2
to
T
is as small as possible. We ignore the movement inside the islands.
Your job is to calculate how small the gap can be.
Note that she assigns a length of the magical bridges before the race starts
once
, 
and does not change the length
during the race
.
Input
The input consists of several datasets. The end of the input is denoted by five zeros separated by a single-space. Each dataset obeys
the
following format. Every number in the inputs is integer.
N
M
S_1
S_2
T
a_1
b_1
w_1
a_2
b_2
w_2
...
a_M
b_M
w_M
(
a_i, b_i
) indicates the bridge
i
connects the two islands
a_i
and
b_i
.
w_i
is either a non-negative integer or a letter
x
(quotes for clarity). If
w_i
is an integer, it indicates the bridge
i
is normal and its length is
w_i
. Otherwise, it indicates the bridge
i
is magical.
You can assume the following:
1\leq N \leq 1,000
1\leq M \leq 2,000
1\leq S_1, S_2, T \leq N
S_1, S_2, T
are all different.
1\leq a_i, b_i \leq N
a_i \neq b_i
For all normal bridge
i
,
0 \leq w_i \leq 1,000,000,000
The number of magical bridges
\leq 100
Output
For each dataset, print the answer in a line.
Sample Input
3 2 2 3 1
1 2 1
1 3 2
4 3 1 4 2
2 1 3
2 3 x
4 3 x
0 0 0 0 0
Output for the Sample Input
1
1

Submitted solutions:

code_snippet: #include<cstdio>
#include<iostream>
#define ll long long
#define abs(x) (x > 0 ? x : -(x))
#define F(a,b,c) ((a) + (b) * (c))
using namespace std;

const int maxn = 1200;
const int maxm = 2200;
const ll inf1 = 1000000000ll * 1100;
const ll inf = (1ll<<60);
int n,m,S1,S2,T,tot;
char ss[110];
int get(char *ss)
{
    int ret = 0;
    for (int i = 0; ss[i]; i++) {
        ret = ret * 10 + ss[i] - '0';
    }
    return ret;
}
ll a[2][110],b[2][110],f[2][110];
struct EE
{
    int to,ne;
    ll w;
    bool f;
}e[maxm * 2];
int L,head[maxn];
void adde(int u,int v,ll w)
{
    e[L].to = v;
    e[L].w = w;
    e[L].f = false;
    if (w == -1) e[L].f = true;
    e[L].ne = head[u];
    head[u] = L++;
}
bool vis[maxn][maxn];
ll dis[2][maxn][maxn];
int que[maxn * maxn][2];
void spfa(int s,int t,int tt)
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j <= tot; j++) {
            dis[tt][i][j] = inf;
            vis[i][j] = false;
        }
    vis[s][0] = true;
    dis[tt][s][0] = 0;
    int fron,rear;
    fron = rear = 0;
    que[rear][0] = s;
    que[rear][1] = 0;
    rear++;
    while (fron != rear) {
        int u1,u2;
        u1 = que[fron][0];
        u2 = que[fron][1];
        vis[u1][u2] = false;
        fron++;
      //  cout<<fron<<' '<<rear<<' '<<u1<<' '<<u2<<endl;
        if (fron == maxn * maxn) fron = 0;
        for (int i = head[u1]; i != -1; i = e[i].ne) {
            int p = e[i].f,v = e[i].to;
            ll w;
            if (u2 + p > tot) continue;
            if (p == 1) w = 0;
            else w = e[i].w;
            if (dis[tt][v][u2 + p] > dis[tt][u1][u2] + w) {
                dis[tt][v][u2 + p] = dis[tt][u1][u2] + w;
                if (!vis[v][u2 + p]) {
                    vis[v][u2 + p] = true;
                    que[rear][0] = v;
                    que[rear][1] = u2 + p;
                    rear++;
                    if (rear == maxn * maxn) rear = 0;
                }
            }
        }
    }
}
int cal(int s,int t,ll x,int tt)
{
    for (int i = 0; i < L; i++)
    if (e[i].f)
        e[i].w = x;
    //spfa(s,t);
    ll w = inf;
    int ret;
    for (int i = 0; i <= tot; i++)
        if (dis[tt][t][i] + i * x <= w) {
            w = dis[tt][t][i] + i * x;
            ret = i;
        }
    return ret;
}
void get(int s,int t,ll *f,ll *a,ll *b,int tt)
{
    ll R = inf1;
    ll now = -1;
    int m = 0;
    while (R >= 0) {
        ll l = 0,r = R;
        while (l < r) {
            ll mid = (l + r + 1) / 2;
            if (cal(s,t,mid,tt) == now)
                r = mid - 1;
            else
                l = mid;
          //  cout<<l<<endl;
        }
       // cout<<l<<endl;
        ll x = cal(s,t,l,tt);
        if (x == now) {
            f[m++] = -1;
            R = -1;
        }
        else {
            now = x;
            a[m] = dis[tt][T][now];
            b[m] = now;
            f[m++] = l;
            R = l;
        }
    }
}
ll cal2(ll a0,ll b0,ll a1,ll b1,ll tmax,ll tmin)
{
    ll l,r;
    l = tmin,r = tmax;
    while (l + 10 < r) {
        ll mid1 = l + (r - l) / 3;
        ll mid2 = l + (r - l) * 2 / 3;
        if (abs(F(a0,b0,mid1) - F(a1,b1,mid1)) > abs(F(a0,b0,mid2) - F(a1,b1,mid2)))
            l = mid1;
        else
            r = mid2;
    }
  //  cout<<l<<' '<<r<<endl;
    ll ret = inf;
    for (ll i = l; i <= r; i++) {
        //cout<<a0<<' '<<b0<<' '<<a1<<' '<<b1<<endl;
        ret = min(ret,abs(F(a0,b0,i) - F(a1,b1,i)));
    }
    return ret;
}
int main()
{
    while (scanf("%d%d%d%d%d",&n,&m,&S1,&S2,&T) != EOF) {
        if (n == 0 && m == 0) return 0;
        S1--;S2--;T--;
        tot = 0;
        L = 0;
        for (int i = 0; i < n; i++) head[i] = -1;
        for (int i = 0; i < m; i++) {
            int a,b,c;
            scanf("%d%d%s",&a,&b,ss);
            a--;
            b--;
            if (ss[0] == 'x') {
                adde(a,b,-1);
                adde(b,a,-1);
                tot++;
            }
            else {
                c = get(ss);
                adde(a,b,c);
                adde(b,a,c);
            }
        }
        for (int i = 0; i <= tot; i++)
            f[0][i] = f[1][i] = -1;
        spfa(S1,T,0);
        spfa(S2,T,1);
        get(S1,T,f[0],a[0],b[0],0);
        get(S2,T,f[1],a[1],b[1],1);
        //continue;
       // return 0;
        int i,j;
        i = 0,j = 0;
        ll ret = inf1;
        //for (int i = 0; i <= 10; i++)
       //     cout<<f[0][i]<<' '<<a[0][i]<<' '<<b[0][i]<<' '<<f[1][i]<<' '<<a[1][i]<<' '<<b[1][i]<<endl;
        while (1) {
            //cout<<i<<' '<<j<<endl;
            ret = min(ret,cal2(a[0][i],b[0][i],a[1][j],b[1][j],min(f[0][i],f[1][j]),max(f[0][i + 1],f[1][j + 1]) + 1));
            if (f[0][i + 1] == -1 && f[1][j + 1] == -1) break;
            //cout<<'x'<<endl;
            if (f[0][i + 1] > f[1][j + 1])
                i++;
            else
                j++;
        }
        cout<<ret<<endl;
    }
}
accuracy: 1
time_ms: 110
memory_kb: 32320
final_rank: 18

code_snippet: // AOJ #2541 Magical Bridges
// 2025.3.18

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using Edge = pair<int, int>;
const ll INF = 1LL << 60;

vector<Edge> graph[1252];
ll dist[1252][125];
ll low[2][125], high[2][125];

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    while (true) {
        int n, m, s1, s2, t;
        cin >> n >> m >> s1 >> s2 >> t;
        if(n==0) break;
        s1--; s2--; t--;

        for (int i = 0; i < n; i++) graph[i].clear();

        for (int i = 0; i < m; i++){
            int a, b;
            char buf[12];
            cin >> a >> b >> buf;
            a--; b--;
            if(buf[0]=='x'){
                graph[a].push_back({b, -1});
                graph[b].push_back({a, -1});
            } else {
                int weight = atoi(buf);
                graph[a].push_back({b, weight});
                graph[b].push_back({a, weight});
            }
        }

        for (int i = 0; i < n; i++) {
            for (int j = 0; j <= 100; j++) dist[i][j] = INF;
        }
        priority_queue<pair<ll,int>> pq;
        dist[t][0] = 0;
        pq.push({0, t * 256 + 0});

        while(!pq.empty()){
            auto cur = pq.top();
            pq.pop();
            ll currentCost = -cur.first;
            int vertex = cur.second / 256;
            int magicCount = cur.second & 255;
            if(dist[vertex][magicCount] != currentCost) continue;

            for(auto edge : graph[vertex]){
                int nextVertex = edge.first;
                int weight = edge.second;
                if(weight == -1) {
                    if(magicCount == 100) continue;
                    if(dist[nextVertex][magicCount+1] > currentCost){
                        dist[nextVertex][magicCount+1] = currentCost;
                        pq.push({-currentCost, nextVertex * 256 + (magicCount+1)});
                    }
                } else {
                    if(dist[nextVertex][magicCount] > currentCost + weight){
                        dist[nextVertex][magicCount] = currentCost + weight;
                        pq.push({-dist[nextVertex][magicCount], nextVertex * 256 + magicCount});
                    }
                }
            }
        }

        int sources[2] = { s1, s2 };
        for (int p = 0; p < 2; p++){
            for (int i = 0; i <= 100; i++){
                if(dist[sources[p]][i] != INF){
                    low[p][i] = 0;
                    high[p][i] = 1LL << 50;
                    for (int j = 0; j <= 100; j++){
                        if(i == j) continue;
                        if(dist[sources[p]][j] == INF) continue;
                        ll a_i = i, b_i = dist[sources[p]][i];
                        ll a_j = j, b_j = dist[sources[p]][j];
                        if(j < i) high[p][i] = min(high[p][i], (b_j - b_i) / (a_i - a_j));
                        else low[p][i] = max(low[p][i], (b_i - b_j + a_j - a_i - 1) / (a_j - a_i));
                    }
                }
            }
        }

        ll ans = INF;
        for (int i = 0; i <= 100; i++){
            for (int j = 0; j <= 100; j++){
                if(dist[s1][i] == INF) continue;
                if(dist[s2][j] == INF) continue;
                ll lowerX = max(low[0][i], low[1][j]);
                ll upperX = min(high[0][i], high[1][j]);
                if(lowerX > upperX) continue;
                ll slope1 = i, intercept1 = dist[s1][i];
                ll slope2 = j, intercept2 = dist[s2][j];
                ll lo = lowerX, hi = upperX;
                while(lo + 5 < hi){
                    ll mid1 = (lo + lo + hi) / 3;
                    ll mid2 = (lo + hi + hi) / 3;
                    ll diff1 = abs(slope1 * mid1 + intercept1 - (slope2 * mid1 + intercept2));
                    ll diff2 = abs(slope1 * mid2 + intercept1 - (slope2 * mid2 + intercept2));
                    if(diff1 < diff2) hi = mid2;
                    else              lo = mid1;
                }
                for (ll x = lo; x <= hi; x++){
                    ll currentDiff = abs(slope1 * x + intercept1 - (slope2 * x + intercept2));
                    ans = min(ans, currentDiff);
                }
            }
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 5968
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct edge {
    long long to, cost;
};

struct range {
    long long l, r, a, b;
};

// =====================================================================================================================================
// ==== Functions
// =====================================================================================================================================
vector<long long> find_magicals(int N, int stt, int goa, vector<vector<edge>> G) {
    vector<vector<long long>> dist(N + 1, vector<long long>(101, (1LL << 60)));
    vector<vector<bool>> used(N + 1, vector<bool>(101, false));
    priority_queue<tuple<long long, int, int>, vector<tuple<long long, int, int>>, greater<tuple<long long, int, int>>> Q;

    // Dijkstra Init
    dist[stt][0] = 0;
    Q.push(make_tuple(0, stt, 0));

    // Dijkstra Main
    while (!Q.empty()) {
        int pos = get<1>(Q.top());
        int num = get<2>(Q.top()); Q.pop();
        if (used[pos][num] == true) continue;
        used[pos][num] = true;
        for (edge e : G[pos]) {
            int nex_num = (num + (e.cost == -1 ? 1 : 0));
            long long new_cost = (e.cost == -1 ? 0 : e.cost);
            if (nex_num <= 100 && dist[e.to][nex_num] > dist[pos][num] + e.cost) {
                dist[e.to][nex_num] = dist[pos][num] + e.cost;
                Q.push(make_tuple(dist[e.to][nex_num], e.to, nex_num));
            }
        }
    }
    
    // Return
    return dist[goa];
}

long long get_shortest(int N, int stt, int goa, long long magical, vector<vector<edge>> G) {
    vector<long long> dist(N + 1, (1LL << 60));
    vector<bool> used(N + 1, false);
    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> Q;

    // Dijkstra Init
    dist[stt] = 0;
    Q.push(make_pair(0, stt));

    // Dijkstra Main
    while (!Q.empty()) {
        int pos = Q.top().second; Q.pop();
        if (used[pos] == true) continue;
        used[pos] = true;
        for (edge e : G[pos]) {
            long long new_cost = (e.cost == -1 ? magical : e.cost);
            if (dist[e.to] > dist[pos] + new_cost) {
                dist[e.to] = dist[pos] + new_cost;
                Q.push(make_pair(dist[e.to], e.to));
            }
        }
    }
    return dist[goa];
}

vector<long long> get_cross(vector<long long> dist) {
    vector<range> r;

    // Simulation
    for (int i = (int)dist.size() - 1; i >= 0; i--) {
        if (dist[i] == (1LL << 60)) continue;
        range new_range = range{0LL, (1LL << 60), 1LL * i, dist[i]};
        long long new_good = (1LL << 60) + 1LL;

        // Main
        while (r.size() >= 1) {
            range last = r[r.size() - 1];
            long long last_prev_good = min((1LL << 60), (new_range.b - last.b) / (last.a - new_range.a));
            if (new_range.b < last.b) last_prev_good = -1;
            if (last.l <= last_prev_good) {
                last.r = last_prev_good;
                new_good = last_prev_good + 1;
                break;
            }
            else {
                r.pop_back();
                new_good = last_prev_good + 1;
            }
        }

        // Update
        if (r.size() == 0) new_good = 0;
        if (new_good <= (1LL << 60)) {
            new_range.l = new_good;
            r.push_back(new_range);
        }
    }

    // Enumerate
    vector<long long> ret;
    for (range rang : r) ret.push_back(rang.l);
    for (range rang : r) ret.push_back(rang.r);
    return ret;
}

long long solve_jury(int N, int M, int S1, int S2, int T, vector<int> A, vector<int> B, vector<int> W) {
    // Step 2. Make Graph
    vector<vector<edge>> G(N + 1, vector<edge>(0));
    for (int i = 0; i < M; i++) G[A[i]].push_back(edge{B[i], W[i]});
    for (int i = 0; i < M; i++) G[B[i]].push_back(edge{A[i], W[i]});

    // Step 3. Get Answer
    long long ans = (1LL << 60);
    for (int i = 0; i <= 10000; i++) {
        long long ret1 = get_shortest(N, S1, T, i, G);
        long long ret2 = get_shortest(N, S2, T, i, G);
        ans = min(ans, abs(ret1 - ret2));
    }
    return ans;
}

long long solve_outp(int N, int M, int S1, int S2, int T, vector<int> A, vector<int> B, vector<int> W) {
    // Step 2. Make Graph
    vector<vector<edge>> G(N + 1, vector<edge>(0));
    for (int i = 0; i < M; i++) G[A[i]].push_back(edge{B[i], W[i]});
    for (int i = 0; i < M; i++) G[B[i]].push_back(edge{A[i], W[i]});

    // Step 3. Get Slope
    vector<long long> dist1 = find_magicals(N, S1, T, G);
    vector<long long> dist2 = find_magicals(N, S2, T, G);

    // Step 4. Get Crosses
    vector<long long> cand = {0LL, 1000000000LL};
    vector<long long> cand1 = get_cross(dist1);
    vector<long long> cand2 = get_cross(dist2);
    for (long long t = -2; t <= 2; t++) {
        for (long long c : cand1) { if (c + t >= 0 && c + t <= (1LL << 45)) cand.push_back(c + t); }
        for (long long c : cand2) { if (c + t >= 0 && c + t <= (1LL << 45)) cand.push_back(c + t); }
    }
    sort(cand.begin(), cand.end());
    cand.erase(unique(cand.begin(), cand.end()), cand.end());

    // Step 5. Find Minimum (Part 1)
    vector<long long> ans_list(cand.size(), 0);
    long long final_ans = (1LL << 60);
    for (int i = 0; i < (int)cand.size(); i++) {
        long long ret1 = get_shortest(N, S1, T, cand[i], G);
        long long ret2 = get_shortest(N, S2, T, cand[i], G);
        ans_list[i] = ret1 - ret2;
        final_ans = min(final_ans, abs(ret1 - ret2));
    }

    // Step 6. Find Minimum (Part 2)
    for (int i = 0; i < (int)cand.size() - 1; i++) {
        long long target = -100000LL;
        if (ans_list[i] > 0 && ans_list[i + 1] < 0) {
            long long slope = abs(ans_list[i + 1] - ans_list[i]) / (cand[i + 1] - cand[i]);
            target = ans_list[i] / slope + cand[i];
        }
        if (ans_list[i] < 0 && ans_list[i + 1] > 0) {
            long long slope = abs(ans_list[i + 1] - ans_list[i]) / (cand[i + 1] - cand[i]);
            target = -ans_list[i] / slope + cand[i];
        }
        if (target != -100000LL) {
            for (int t = -1; t <= 1; t++) {
                long long dst = target + t; if (dst < 0) continue;
                long long ret1 = get_shortest(N, S1, T, dst, G);
                long long ret2 = get_shortest(N, S2, T, dst, G);
                final_ans = min(final_ans, abs(ret1 - ret2));
            }
        }
    }

    // Return
    return final_ans;
}

// =====================================================================================================================================
// ==== Main
// =====================================================================================================================================
int main() {
    int DEBUG = 1;
    
    if (DEBUG == 1) {
        while (true) {
            int N, M, S1, S2, T; cin >> N >> M >> S1 >> S2 >> T;
            if (N + M + S1 + S2 + T == 0) break;
            vector<int> A(M, 0);
            vector<int> B(M, 0);
            vector<int> W(M, 0);
            for (int i = 0; i < M; i++) {
                string str; cin >> A[i] >> B[i] >> str;
                if (str == "x") W[i] = -1;
                else W[i] = stoi(str);
            }
            cout << solve_outp(N, M, S1, S2, T, A, B, W) << endl;
        }
    }

    else {
        for (int t = 1; t <= 100000; t++) {
            cerr << t << endl;
            int N = 7;
            int M = 10;
            int S1 = rand() % N + 1;
            int S2 = rand() % N + 1;
            int T = rand() % N + 1;
            vector<int> A(M, 0);
            vector<int> B(M, 0);
            vector<int> W(M, 0);
            for (int i = 0; i < N - 1; i++) A[i] = i + 1;
            for (int i = 0; i < N - 1; i++) B[i] = i + 2;
            for (int i = N - 1; i < M; i++) {
                A[i] = rand() % N + 1;
                B[i] = rand() % N + 1;
            }
            for (int i = 0; i < M; i++) W[i] = (rand() % 2 == 0 ? -1 : rand() % 1001);
            /*if (t == 39) {
                cout << "Wrong Answer on Test #" << t << endl;
                cout << N << " " << M << " " << S1 << " " << S2 << " " << T << endl;
                for (int i = 0; i < M; i++) cout << A[i] << " " << B[i] << " " << (W[i] == -1 ? "x" : to_string(W[i])) << endl;
                return 0;
            }*/

            long long ret1 = solve_jury(N, M, S1, S2, T, A, B, W);
            long long ret2 = solve_outp(N, M, S1, S2, T, A, B, W);
            if (ret1 != ret2) {
                cout << "Wrong Answer on Test #" << t << endl;
                cout << "Jury = " << ret1 << ", Output = " << ret2 << endl;
                cout << N << " " << M << " " << S1 << " " << S2 << " " << T << endl;
                for (int i = 0; i < M; i++) cout << A[i] << " " << B[i] << " " << (W[i] == -1 ? "x" : to_string(W[i])) << endl;
                return 0;
            }
        }
    }
    return 0;
}
accuracy: 1
time_ms: 410
memory_kb: 6052
final_rank: 8

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int main() {
while(1) {
    int N, M, S1, S2, T;
    cin >> N >> M >> S1 >> S2 >> T;
    S1--,S2--,T--;
    if (N == 0) return 0;
    vector<vector<pair<int,ll>>> G(N);
    rep(i,0,M) {
        int A, B;
        string C;
        cin >> A >> B >> C;
        A--, B--;
        ll X;
        if (C == "x") X = -1;
        else X = stoll(C);
        G[A].push_back({B,X});
        G[B].push_back({A,X});
    }
    int L = 100;
    vector<vector<ll>> DP(N,vector<ll>(L+1,INF));
    DP[T][0] = 0;
    priority_queue<pair<ll,pair<int,int>>,vector<pair<ll,pair<int,int>>>,greater<pair<ll,pair<int,int>>>> PQ;
    PQ.push({0,{T,0}});
    while(!PQ.empty()) {
        auto [D,P] = PQ.top();
        auto [X,Y] = P;
        PQ.pop();
        if (DP[X][Y] < D) continue;
        for (auto E : G[X]) {
            auto [NX, C] = E;
            if (C == -1) {
                if (Y == L) continue;
                if (chmin(DP[NX][Y+1],D)) {
                    PQ.push({D,{NX,Y+1}});
                }
            }
            else {
                if (chmin(DP[NX][Y],D+C)) {
                    PQ.push({D+C,{NX,Y}});
                }
            }
        }
    }
    vector<ll> D1 = DP[S1], D2 = DP[S2];
    auto Calc = [&](ll X) -> ll {
        ll MIN1 = INF;
        rep(i,0,L+1) {
            if (D1[i] == INF) continue;
            chmin(MIN1, D1[i] + X * (ll)i);
        }
        ll MIN2 = INF;
        rep(i,0,L+1) {
            if (D2[i] == INF) continue;
            chmin(MIN2, D2[i] + X * (ll)i);
        }
        return abs(MIN1-MIN2);
    };
    ll ANS = Calc(0);
    rep(i,0,L+1) {
        if (D1[i] == INF) continue;
        rep(j,0,L+1) {
            if (D1[j] == INF) continue;
            if (i == j) continue;
            ll L = floor(D1[j]-D1[i],i-j);
            ll R = ceil(D1[j]-D1[i],i-j);
            if (L >= 0) chmin(ANS, Calc(L));
            if (R >= 0) chmin(ANS, Calc(R));
        }
    }
    rep(i,0,L+1) {
        if (D2[i] == INF) continue;
        rep(j,0,L+1) {
            if (D2[j] == INF) continue;
            if (i == j) continue;
            ll L = floor(D2[j]-D2[i],i-j);
            ll R = ceil(D2[j]-D2[i],i-j);
            if (L >= 0) chmin(ANS, Calc(L));
            if (R >= 0) chmin(ANS, Calc(R));
        }
    }
    rep(i,0,L+1) {
        if (D1[i] == INF) continue;
        rep(j,0,L+1) {
            if (D2[j] == INF) continue;
            if (i == j) continue;
            ll L = floor(D2[j]-D1[i],i-j);
            ll R = ceil(D2[j]-D1[i],i-j);
            if (L >= 0) chmin(ANS, Calc(L));
            if (R >= 0) chmin(ANS, Calc(R));
        }
    }
    cout << ANS << endl;
}
}
accuracy: 1
time_ms: 830
memory_kb: 5808
final_rank: 16

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;

ll m1,m2;
ll calc(ll y,vector<ll> &dist,bool L=0){
    ll n=dist.size();
    ll res=1e18;
    for(int i=0;i<n;i++){
        if(dist[i]>1e17)continue;
        if(res>dist[i]+i*y){
            res=dist[i]+i*y;
            (L?m2:m1)=i;
        }
    }
    return res;
}


void solve(ll N,ll M,ll S1,ll S2,ll T){
    S1--;S2--;T--;
    
    vector<vector<pair<ll,ll>>> G(N);
    for(int i=0;i<M;i++){
        int A,B;
        string S;
        cin>>A>>B>>S;
        A--;B--;
        ll W=(S[0]=='x'?-1:stoll(S));
        G[A].push_back({B,W});
        G[B].push_back({A,W});
    }
    vector<vector<ll>> DP(N,vector<ll>(110,1e18));
    vector<vector<bool>> seen(N,vector<bool>(110,0));
    priority_queue<pair<ll,pair<ll,ll>>,vector<pair<ll,pair<ll,ll>>>,greater<pair<ll,pair<ll,ll>>>> Q;
    Q.push({0,{T,0}});
    DP[T][0]=0;
    while(!Q.empty()){
        ll c=Q.top().first;
        ll n=Q.top().second.first;
        ll d=Q.top().second.second;
        Q.pop();
        if(seen[n][d])continue;
        seen[n][d]=1;
        for(auto [v,w]:G[n]){
            if(w!=-1){
                ll nc=c+w;
                if(DP[v][d]>nc){
                    DP[v][d]=nc;
                    Q.push({nc,{v,d}});
                }
            }
            else if(d<109){
                ll nd=d+1;
                if(DP[v][nd]>c){
                    DP[v][nd]=c;
                    Q.push({c,{v,d+1}});
                }
            }
        }
    }
    vector<vector<int>> mindex(N,vector<int>(110,-1));
    DP={DP[S1],DP[S2]};
    N=2;
    set<ll> EV;
    EV.insert(0);
    EV.insert(1e15);
    for(int n=0;n<N;n++){
        if(DP[n][0]<1e17)mindex[n][0]=0;
        for(int m=0;m<109;m++){
            if(DP[n][m+1]>=DP[n][m]){
                DP[n][m+1]=DP[n][m];
                mindex[n][m+1]=mindex[n][m];
            }
            else if(DP[n][m+1]<1e17){
                mindex[n][m+1]=m+1;
                for(int m2=0;m2<=m;m2++){
                    if(mindex[n][m2]==m2){
                        ll d=m+1-m2;
                        ll a=DP[n][m2]-DP[n][m+1];
                        ll x=a/d;
                        for(ll y=x-1;y<=x+1;y++)if(y>0&&y<1e15)EV.insert(y);
                    }
                }
            }
        }
    }
    vector<ll> P;
    for(auto y:EV)P.push_back(y);
    
    ll an=1e18;
    if(DP[0][0]<1e17&&DP[1][0]<1e17)an=abs(DP[0][0]-DP[1][0]);
    int PN=P.size();
    for(int i=0;i+1<PN;i++){
        m1=1e18,m2=1e18;
        ll d1=calc(P[i],DP[0]);
        ll d2=calc(P[i],DP[1]);
        ll D1=calc(P[i+1],DP[0]);
        ll D2=calc(P[i+1],DP[1],1);
        an=min(an,abs(d1-d2));
        an=min(an,abs(D1-D2));
        if(abs(P[i+1]-P[i])<2)continue;
        ll u=abs(D1-D2),v=abs(m1-m2);
        if(v==0||v>1e17)continue;
        for(ll yy=P[i+1]-u/v-1;yy<=P[i+1]-u/v+1;yy++)if(yy>=0)an=min(an,abs(calc(yy,DP[0])-calc(yy,DP[1])));
    }
    cout<<an<<endl;
}

int main() {
    ll N,M,S1,S2,T;
    while(cin>>N>>M>>S1>>S2>>T,N+M!=0)solve(N,M,S1,S2,T);
}
accuracy: 1
time_ms: 450
memory_kb: 7216
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;

ll m1,m2;
ll calc(ll y,vector<ll> &dist,bool L=0){
    ll n=dist.size();
    ll res=1e18;
    for(int i=0;i<n;i++){
        if(dist[i]>1e17)continue;
        if(res>dist[i]+i*y){
            res=dist[i]+i*y;
            (L?m2:m1)=i;
        }
    }
    return res;
}


void solve(ll N,ll M,ll S1,ll S2,ll T){
    S1--;S2--;T--;
    
    vector<vector<pair<ll,ll>>> G(N);
    for(int i=0;i<M;i++){
        int A,B;
        string S;
        cin>>A>>B>>S;
        A--;B--;
        ll W=(S[0]=='x'?-1:stoll(S));
        G[A].push_back({B,W});
        G[B].push_back({A,W});
    }
    vector<vector<ll>> DP(N,vector<ll>(110,1e18));
    vector<vector<bool>> seen(N,vector<bool>(110,0));
    priority_queue<pair<ll,pair<ll,ll>>,vector<pair<ll,pair<ll,ll>>>,greater<pair<ll,pair<ll,ll>>>> Q;
    Q.push({0,{T,0}});
    DP[T][0]=0;
    while(!Q.empty()){
        ll c=Q.top().first;
        ll n=Q.top().second.first;
        ll d=Q.top().second.second;
        Q.pop();
        if(seen[n][d])continue;
        seen[n][d]=1;
        for(auto [v,w]:G[n]){
            if(w!=-1){
                ll nc=c+w;
                if(DP[v][d]>nc){
                    DP[v][d]=nc;
                    Q.push({nc,{v,d}});
                }
            }
            else if(d<109){
                ll nd=d+1;
                if(DP[v][nd]>c){
                    DP[v][nd]=c;
                    Q.push({c,{v,d+1}});
                }
            }
        }
    }
    vector<vector<int>> mindex(N,vector<int>(110,-1));
    DP={DP[S1],DP[S2]};
    N=2;
    set<ll> EV;
    EV.insert(0);
    EV.insert(1e15);
    for(int n=0;n<N;n++){
        if(DP[n][0]<1e17)mindex[n][0]=0;
        for(int m=0;m<109;m++){
            if(DP[n][m+1]>=DP[n][m]){
                DP[n][m+1]=DP[n][m];
                mindex[n][m+1]=mindex[n][m];
            }
            else if(DP[n][m+1]<1e17){
                mindex[n][m+1]=m+1;
                for(int m2=0;m2<=m;m2++){
                    if(mindex[n][m2]==m2){
                        ll d=m+1-m2;
                        ll a=DP[n][m2]-DP[n][m+1];
                        ll x=a/d;
                        for(ll y=x-2;y<=x+2;y++){
                            if(y>0&&y<1e15)EV.insert(y);
                        }
                    }
                }
            }
            
        }
    }
    vector<ll> P;
    for(auto y:EV)P.push_back(y);
    
    
    ll an=1e18;
    if(DP[0][0]<1e17&&DP[1][0]<1e17)an=abs(DP[0][0]-DP[1][0]);
    int PN=P.size();
    for(int i=0;i+1<PN;i++){

        m1=1e18,m2=1e18;
        ll d1=calc(P[i],DP[0]);
        ll d2=calc(P[i],DP[1]);
        ll D1=calc(P[i+1],DP[0]);
        ll D2=calc(P[i+1],DP[1],1);
        an=min(an,abs(d1-d2));
        an=min(an,abs(D1-D2));
        if(abs(P[i+1]-P[i])<2)continue;
        if(1){
            ll u=abs(D1-D2);
            ll v=abs(m1-m2);
            if(v==0||v>1e17)continue;
            for(ll yy=P[i+1]-u/v-2;yy<=P[i+1]-u/v+2;yy++){
                if(yy>=0)an=min(an,abs(calc(yy,DP[0])-calc(yy,DP[1])));
            }
        }
        
    }
    cout<<an<<endl;
}

int main() {
    ll N,M,S1,S2,T;
    while(cin>>N>>M>>S1>>S2>>T,N+M!=0)solve(N,M,S1,S2,T);
    
}
accuracy: 1
time_ms: 600
memory_kb: 7348
final_rank: 14

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;

ll m1,m2;
ll calc(ll y,vector<ll> &dist,bool L=0){
    ll n=dist.size();
    ll res=1e18;
    for(int i=0;i<n;i++){
        if(dist[i]>1e17)continue;
        if(res>dist[i]+i*y){
            res=dist[i]+i*y;
            (L?m2:m1)=i;
        }
    }
    return res;
}

ll cnte=0;
ll target=414216;

void solve(ll N,ll M,ll S1,ll S2,ll T){
    cnte++;
    S1--;S2--;T--;
    
    vector<vector<pair<ll,ll>>> G(N);
    // cnte++;
    for(int i=0;i<M;i++){
        int A,B;
        string S;
        
        cin>>A>>B>>S;
        if(cnte==target){
            cout<<A<<" "<<B<<" "<<S<<endl;
        }
        A--;B--;
        ll W=(S[0]=='x'?-1:stoll(S));
        G[A].push_back({B,W});
        G[B].push_back({A,W});
    }
    vector<vector<ll>> DP(N,vector<ll>(110,1e18));
    vector<vector<bool>> seen(N,vector<bool>(110,0));
    priority_queue<pair<ll,pair<ll,ll>>,vector<pair<ll,pair<ll,ll>>>,greater<pair<ll,pair<ll,ll>>>> Q;
    Q.push({0,{T,0}});
    DP[T][0]=0;
    while(!Q.empty()){
        ll c=Q.top().first;
        ll n=Q.top().second.first;
        ll d=Q.top().second.second;
        Q.pop();
        if(seen[n][d])continue;
        seen[n][d]=1;
        for(auto [v,w]:G[n]){
            if(w!=-1){
                ll nc=c+w;
                if(DP[v][d]>nc){
                    DP[v][d]=nc;
                    Q.push({nc,{v,d}});
                }
            }
            else if(d<109){
                ll nd=d+1;
                if(DP[v][nd]>c){
                    DP[v][nd]=c;
                    Q.push({c,{v,d+1}});
                }
            }
        }
    }
    vector<vector<int>> mindex(N,vector<int>(110,-1));
    DP={DP[S1],DP[S2]};
    N=2;
    set<ll> EV;
    EV.insert(0);
    EV.insert(1e15);
    for(int n=0;n<N;n++){
        if(DP[n][0]<1e17)mindex[n][0]=0;
        for(int m=0;m<109;m++){
            if(DP[n][m+1]>=DP[n][m]){
                DP[n][m+1]=DP[n][m];
                mindex[n][m+1]=mindex[n][m];
            }
            else if(DP[n][m+1]<1e17){
                mindex[n][m+1]=m+1;
                for(int m2=0;m2<=m;m2++){
                    if(mindex[n][m2]==m2){
                        ll d=m+1-m2;
                        ll a=DP[n][m2]-DP[n][m+1];
                        ll x=a/d;
                        for(ll y=x-2;y<=x+2;y++){
                            if(y>0&&y<1e15)EV.insert(y);
                        }
                    }
                }
            }
            
        }
    }
    vector<ll> P;
    for(auto y:EV)P.push_back(y);
    
    
    ll an=1e18;
    if(DP[0][0]<1e17&&DP[1][0]<1e17)an=abs(DP[0][0]-DP[1][0]);
    int PN=P.size();
    for(int i=0;i+1<PN;i++){

        m1=1e18,m2=1e18;
        ll d1=calc(P[i],DP[0]);
        ll d2=calc(P[i],DP[1]);
        ll D1=calc(P[i+1],DP[0]);
        ll D2=calc(P[i+1],DP[1],1);
        an=min(an,abs(d1-d2));
        an=min(an,abs(D1-D2));
        if(abs(P[i+1]-P[i])<2)continue;
        ll E1=calc(P[i+1]-1,DP[0]);
        ll E2=calc(P[i+1]-1,DP[1],1);
        an=min(an,abs(E1-E2));
        bool CL=0;
        if(d1<=d2&&E1>=E2){
            CL=1;
        }
        if(d1>=d2&&E1<=E2){
            CL=1;
        }
        if(CL){
            ll u=abs(E1-E2);
            ll v=abs(m1-m2);
            if(v==0||v>1e17)continue;
            for(ll yy=P[i+1]-u/v-2;yy<=P[i+1]-u/v+2;yy++){
                if(yy>=0)an=min(an,abs(calc(yy,DP[0])-calc(yy,DP[1])));
            }
        }
        
    }
    cout<<an<<endl;
}

int main() {
    ll N,M,S1,S2,T;
    while(cin>>N>>M>>S1>>S2>>T,N+M!=0)solve(N,M,S1,S2,T);
    
}
accuracy: 1
time_ms: 570
memory_kb: 7128
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

template<class T>
bool chmin(T &a, const T &b) {if (a > b) {a = b; return 1;} return 0;}

using ll = long long;


bool is_end = false;
ll cnt = 0;

ll distance(vector<ll> &ds, vector<ll> &dt, ll x) {
  ll s = 1e18, t = 1e18;
  for (int i = 0; i < (int)ds.size(); ++i) chmin(s, i * x + ds[i]);
  for (int i = 0; i < (int)dt.size(); ++i) chmin(t, i * x + dt[i]);
  
  return s - t;
}

// // i0 < i1 => i0 * x + b0 <= i1 * x + b1 なる min_x 
// ll jump(ll i0, ll b0, ll i1, ll b1) {
//   const ll INF = 1e14;
//   ll ok = INF, ng = -1;
  
//   while (abs(ok - ng) > 1) {
//     ll mid = (ok + ng) / 2;
//     ll d0 = i0 * mid + b0;
//     ll d1 = i1 * mid + b1;
//     if (d0 <= d1) ok = mid;
//     else ng = mid;
//   }
  
//   return ok;
// }

array<ll, 2> intersect(array<ll, 2> l0, array<ll, 2> l1, array<ll, 2> l2) {
  auto [a, b] = l0;
  auto [c, d] = l1;
  auto [e, f] = l2;
  
  ll f01 = (d - b) / (a - c);
  ll f12 = (f - d) / (c - e);
  
  return {f01, f12};
}

void solve() {
  ll N, M, S, T, U; cin >> N >> M >> S >> T >> U;
  if (N + M + S + T + U == 0) {
    is_end = true;
    return;
  }
  S--, T--, U--;
  vector< vector<array<ll, 2>> > graph(N);
  for (int i = 0; i < M; ++i) {
    ll a, b; cin >> a >> b;
    a--, b--;
    string s; cin >> s;
    ll w = -1;
    if (s == "x") w = -1;
    else w = stoi(s);
    
    graph[a].push_back({b, w});
    graph[b].push_back({a, w});
  }
  
  const ll INF = 1e15;
  vector distS(N, vector<ll>(110, INF));
  vector distT = distS;
  
  // distance from S / T
  {
    priority_queue< array<ll, 3>, vector<array<ll, 3>>, greater<array<ll, 3>> > pq;
    distS[S][0] = 0;
    pq.push({distS[S][0], S, 0});
    
    while (pq.size()) {
      auto [d, v, k] = pq.top();
      pq.pop();
      if (distS[v][k] < d) continue;
      
      for (auto [to, w] : graph[v]) {
        ll nd = d + w, nv = to, nk = k;
        if (w == -1) nd = d, nk = k + 1;
        if (nk < 110) {
          if (chmin(distS[nv][nk], nd)) pq.push({distS[nv][nk], nv, nk});
        }
      }
    }
    
  }
  
  {
    priority_queue< array<ll, 3>, vector<array<ll, 3>>, greater<array<ll, 3>> > pq;
    distT[T][0] = 0;
    pq.push({distT[T][0], T, 0});
    
    while (pq.size()) {
      auto [d, v, k] = pq.top();
      pq.pop();
      if (distT[v][k] < d) continue;
      
      for (auto [to, w] : graph[v]) {
        ll nd = d + w, nv = to, nk = k;
        if (w == -1) nd = d, nk = k + 1;
        if (nk < 110) {
          if (chmin(distT[nv][nk], nd)) pq.push({distT[nv][nk], nv, nk});
        }
      }
    }
    
  }
  
  vector<ll> ds, dt;
  for (int k = 0; k+1 < 110; ++k) {
    ds.emplace_back(distS[U][k]);
    dt.emplace_back(distT[U][k]);
  }
  
  // cout << -1 << endl;
  // for (int k = 0; k < 10; ++k) cout << ds[k] << " ";
  // cout << endl;
  // for (int k = 0; k < 10; ++k) cout << dt[k] << " ";
  // cout << endl;
  
  // calculate intersect point by CHT
  vector<ll> pos;
  pos.emplace_back(INF / 10);
  pos.emplace_back(0);
  {
    vector<array<ll, 2>> stc;
    for (int k = 108; k >= 0; --k) {
      if (ds[k] == INF) continue;
      
      stc.push_back({k, ds[k]});
      
      while (stc.size() >= 3) {
        auto b2 = stc.back();
        stc.pop_back();
        auto b1 = stc.back();
        stc.pop_back();
        auto b0 = stc.back();
        
        auto [f01, f12] = intersect(b0, b1, b2);
        
        if (f01 < f12) {
          stc.emplace_back(b1);
          stc.emplace_back(b2);
          break;
        }
        else {
          stc.emplace_back(b2);
        }
      }
    }
    for (int i = 0; i+1 < stc.size(); ++i) {
      auto b0 = stc[i];
      auto b1 = stc[i+1];
      auto [f01, f12] = intersect(b0, b1, {-1, -1});
      pos.emplace_back(f01);
    }
  }
  {
    vector<array<ll, 2>> stc;
    for (int k = 108; k >= 0; --k) {
      if (dt[k] == INF) continue;
      
      stc.push_back({k, dt[k]});
      
      while (stc.size() >= 3) {
        auto b2 = stc.back();
        stc.pop_back();
        auto b1 = stc.back();
        stc.pop_back();
        auto b0 = stc.back();
        
        auto [f01, f12] = intersect(b0, b1, b2);
        
        if (f01 < f12) {
          stc.emplace_back(b1);
          stc.emplace_back(b2);
          break;
        }
        else {
          stc.emplace_back(b2);
        }
      }
    }
    for (int i = 0; i+1 < stc.size(); ++i) {
      auto b0 = stc[i];
      auto b1 = stc[i+1];
      auto [f01, f12] = intersect(b0, b1, {-1, -1});
      pos.emplace_back(f01);
    }
  }
  
  sort(pos.begin(), pos.end());
  pos.erase(unique(pos.begin(), pos.end()), pos.end());
  
  // calculate answer by ternary search
  ll res = 1e18;
  for (int i = 0; i+1 < pos.size(); ++i) {
    ll l = pos[i], r = pos[i+1];
    l = max(l, 0LL), r = max(r, 0LL);
    while (abs(l - r) > 2) {
      ll m1 = (2 * l + r) / 3;
      ll m2 = (l + 2 * r) / 3;
      
      ll d1 = abs(distance(ds, dt, m1));
      ll d2 = abs(distance(ds, dt, m2));
      if (d1 < d2) r = m2;
      else l = m1;
    }
    
    for (ll m = l; m <= r; ++m) {
      if (m < 0) continue;
      ll d = abs(distance(ds, dt, m));
      chmin(res, d);
    }
    
  }
  cout << res << endl;
  
  return;
}

int main() {
  
  while (!is_end) {
    solve();
  }
  
  return 0;
}
accuracy: 1
time_ms: 400
memory_kb: 10736
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;

template<class T>
bool chmin(T &a, const T &b) {if (a > b) {a = b; return 1;} return 0;}

using ll = long long;


bool is_end = false;
ll cnt = 0;

ll distance(vector<ll> &ds, vector<ll> &dt, ll x) {
  ll s = 1e18, t = 1e18;
  for (int i = 0; i < (int)ds.size(); ++i) chmin(s, i * x + ds[i]);
  for (int i = 0; i < (int)dt.size(); ++i) chmin(t, i * x + dt[i]);
  
  return s - t;
}

// // i0 < i1 => i0 * x + b0 <= i1 * x + b1 なる min_x 
// ll jump(ll i0, ll b0, ll i1, ll b1) {
//   const ll INF = 1e14;
//   ll ok = INF, ng = -1;
  
//   while (abs(ok - ng) > 1) {
//     ll mid = (ok + ng) / 2;
//     ll d0 = i0 * mid + b0;
//     ll d1 = i1 * mid + b1;
//     if (d0 <= d1) ok = mid;
//     else ng = mid;
//   }
  
//   return ok;
// }

array<ll, 2> intersect(array<ll, 2> l0, array<ll, 2> l1, array<ll, 2> l2) {
  auto [a, b] = l0;
  auto [c, d] = l1;
  auto [e, f] = l2;
  
  ll f01 = (d - b) / (a - c);
  ll f12 = (f - d) / (c - e);
  
  return {f01, f12};
}

void solve() {
  ll N, M, S, T, U; cin >> N >> M >> S >> T >> U;
  if (N + M + S + T + U == 0) {
    is_end = true;
    return;
  }
  S--, T--, U--;
  vector< vector<array<ll, 2>> > graph(N);
  for (int i = 0; i < M; ++i) {
    ll a, b; cin >> a >> b;
    a--, b--;
    string s; cin >> s;
    ll w = -1;
    if (s == "x") w = -1;
    else w = stoi(s);
    
    graph[a].push_back({b, w});
    graph[b].push_back({a, w});
  }
  
  cnt++;
  // if (cnt == 50) {
  //   cout << N << " " << M << " " << S << " " << T << " " << U << endl;
  //   for (int i = 0; i < N; ++i) {
  //     for (auto [t, w] : graph[i]) {
  //       cout << i << " " << t << " " << w << endl;
  //     }
  //   }
  // }
  
  const ll INF = 1e15;
  vector distS(N, vector<ll>(110, INF));
  vector distT = distS;
  
  // distance from S / T
  {
    priority_queue< array<ll, 3>, vector<array<ll, 3>>, greater<array<ll, 3>> > pq;
    distS[S][0] = 0;
    pq.push({distS[S][0], S, 0});
    
    while (pq.size()) {
      auto [d, v, k] = pq.top();
      pq.pop();
      if (distS[v][k] < d) continue;
      
      for (auto [to, w] : graph[v]) {
        ll nd = d + w, nv = to, nk = k;
        if (w == -1) nd = d, nk = k + 1;
        if (nk < 110) {
          if (chmin(distS[nv][nk], nd)) pq.push({distS[nv][nk], nv, nk});
        }
      }
    }
    
  }
  
  {
    priority_queue< array<ll, 3>, vector<array<ll, 3>>, greater<array<ll, 3>> > pq;
    distT[T][0] = 0;
    pq.push({distT[T][0], T, 0});
    
    while (pq.size()) {
      auto [d, v, k] = pq.top();
      pq.pop();
      if (distT[v][k] < d) continue;
      
      for (auto [to, w] : graph[v]) {
        ll nd = d + w, nv = to, nk = k;
        if (w == -1) nd = d, nk = k + 1;
        if (nk < 110) {
          if (chmin(distT[nv][nk], nd)) pq.push({distT[nv][nk], nv, nk});
        }
      }
    }
    
  }
  
  vector<ll> ds, dt;
  for (int k = 0; k+1 < 110; ++k) {
    ds.emplace_back(distS[U][k]);
    dt.emplace_back(distT[U][k]);
  }
  
  // cout << -1 << endl;
  // for (int k = 0; k < 10; ++k) cout << ds[k] << " ";
  // cout << endl;
  // for (int k = 0; k < 10; ++k) cout << dt[k] << " ";
  // cout << endl;
  

  
  // calculate intersect point by CHT
  vector<ll> pos;
  pos.emplace_back(INF / 10);
  pos.emplace_back(0);
  {
    vector<array<ll, 2>> stc;
    for (int k = 108; k >= 0; --k) {
      if (ds[k] == INF) continue;
      
      stc.push_back({k, ds[k]});
      
      while (stc.size() >= 3) {
        auto b2 = stc.back();
        stc.pop_back();
        auto b1 = stc.back();
        stc.pop_back();
        auto b0 = stc.back();
        
        auto [f01, f12] = intersect(b0, b1, b2);
        
        if (f01 < f12) {
          stc.emplace_back(b1);
          stc.emplace_back(b2);
          break;
        }
        else {
          stc.emplace_back(b2);
        }
      }
    }
    for (int i = 0; i+1 < stc.size(); ++i) {
      auto b0 = stc[i];
      auto b1 = stc[i+1];
      auto [f01, f12] = intersect(b0, b1, {-1, -1});
      pos.emplace_back(f01);
    }
  }
  {
    vector<array<ll, 2>> stc;
    for (int k = 108; k >= 0; --k) {
      if (dt[k] == INF) continue;
      
      stc.push_back({k, dt[k]});
      
      while (stc.size() >= 3) {
        auto b2 = stc.back();
        stc.pop_back();
        auto b1 = stc.back();
        stc.pop_back();
        auto b0 = stc.back();
        
        auto [f01, f12] = intersect(b0, b1, b2);
        
        if (f01 < f12) {
          stc.emplace_back(b1);
          stc.emplace_back(b2);
          break;
        }
        else {
          stc.emplace_back(b2);
        }
      }
    }
    for (int i = 0; i+1 < stc.size(); ++i) {
      auto b0 = stc[i];
      auto b1 = stc[i+1];
      auto [f01, f12] = intersect(b0, b1, {-1, -1});
      pos.emplace_back(f01);
    }
  }
  
  sort(pos.begin(), pos.end());
  pos.erase(unique(pos.begin(), pos.end()), pos.end());
  
  // if (cnt == 50) {
  //   for (auto p : pos) {
  //     cout << p/3 << " " << distance(ds, dt, p/3) << endl;
  //     cout << p/3*2 << " " << distance(ds, dt, p/3*2) << endl;
  //     cout << p << " " << distance(ds, dt, p) << endl;
  //   }
  //   cout << endl;
  // }
  
  ll res = 1e18;
  for (int i = 0; i+1 < pos.size(); ++i) {
    ll l = pos[i], r = pos[i+1];
    l = max(l, 0LL), r = max(r, 0LL);
    while (abs(l - r) > 2) {
      ll m1 = (2 * l + r) / 3;
      ll m2 = (l + 2 * r) / 3;
      
      ll d1 = abs(distance(ds, dt, m1));
      ll d2 = abs(distance(ds, dt, m2));
      if (d1 < d2) r = m2;
      else l = m1;
    }
    
    for (ll m = l; m <= r; ++m) {
      if (m < 0) continue;
      ll d = abs(distance(ds, dt, m));
      chmin(res, d);
    }
    
  }
  cout << res << endl;
  
  return;
}

int main() {
  
  while (!is_end) {
    solve();
  }
  
  return 0;
}
accuracy: 1
time_ms: 410
memory_kb: 9960
final_rank: 12

code_snippet: #pragma region template
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
#ifdef __LOCAL
 #include <debug>
#else
 #define debug(...) void(0)
#endif

using ll=long long;
using ld=long double;
using vi=vector<int>;
using vll=vector<ll>;
using pi=pair<int,int>;
using pll=pair<ll,ll>;

#define overload2(a,b,c,...) c
#define overload3(a,b,c,d,...) d
#define overload4(a,b,c,d,e,...) e
#define overload5(a,b,c,d,e,f,...) f

#define TYPE1(T) template<typename T>
#define TYPE2(T,U) template<typename T,typename U>
#define TYPE(...) overload2(__VA_ARGS__,TYPE2,TYPE1)(__VA_ARGS__)
#define TYPES1(T) template<typename... T>
#define TYPES2(H,T) template<typename H,typename... T>
#define TYPES(...) overload2(__VA_ARGS__,TYPES2,TYPES1)(__VA_ARGS__)

#define REP4(i,s,n,d) for(ll i=(s);i<(n);i+=(d))
#define REP3(i,s,n) REP4(i,s,n,1)
#define REP2(i,n) REP3(i,0,n)
#define REP1(n) REP2(tomato,n)
#define REP(...) overload4(__VA_ARGS__,REP4,REP3,REP2,REP1)(__VA_ARGS__)

#define RREP4(i,s,n,d) for(ll i=(n)-1;i>=s;i-=d)
#define RREP3(i,s,n) RREP4(i,s,n,1)
#define RREP2(i,n) RREP3(i,0,n)
#define RREP1(n) RREP2(tomato,n)
#define RREP(...) overload4(__VA_ARGS__,RREP4,RREP3,RREP2,RREP1)(__VA_ARGS__)

#define ALL(v) v.begin(),v.end()
#define RALL(v) v.rbegin(),v.rend()
#define SORT(v) sort(ALL(v))
#define RSORT(v) sort(RALL(v))
#define REVERSE(v) reverse(ALL(v))
#define UNIQUE(v) SORT(v),v.erase(unique(ALL(v)),v.end())

TYPES(T) void input(T&... a){ (cin>>...>>a); }
#define DECLARE(T,...) T __VA_ARGS__;input(__VA_ARGS__);
#define INT(...) DECLARE(int,__VA_ARGS__)
#define STR(...) DECLARE(string,__VA_ARGS__)
#define LL(...) DECLARE(long long,__VA_ARGS__)
#define CHR(...) DECLARE(char,__VA_ARGS__)
#define DBL(...) DECLARE(double,__VA_ARGS__)

TYPE(T)
istream&operator>>(istream&is,vector<T>&v){
  for(auto&a:v)cin>>a;
  return is;
}
TYPE(T)
ostream&operator<<(ostream&os,vector<T>&v){
  if(&os==&cerr)os<<"[";
  REP(i,v.size()){
    os<<v[i];
    if(i+1<v.size())os<<(&os==&cerr?",":" ");
  }
  if(&os==&cerr)os<<"]";
  return os;
}

#pragma endregion template

template<typename T>
struct Edge{
  int to;
  T cost;
};
 
template<typename T>
struct WeightedGraph:vector<vector<Edge<T>>>{
  WeightedGraph(){}
  WeightedGraph(int n){
    (*this).resize(n);
  }
    
  void add_edge(int from, int to, T cost){
    (*this)[from].push_back({to,cost});
  }
};

TYPE(T) using pq = priority_queue<T>;
TYPE(T) using pqg = priority_queue<T, vector<T>, greater<T>>;

template<typename T>
bool chmin(T &a,T b){
  return (a>b&&(a=b,true));
}

//#include <atcoder/dsu>
//using namespace atcoder;

const long long LINF=1e18;

template<typename T,typename Comp>
using pque=priority_queue<T,vector<T>,Comp>;

template<typename T>
vector<T> dijkstra(const WeightedGraph<T> &g,int s=0){
  vector<T> d(g.size(),numeric_limits<T>::max()/2);
  pque<pair<T,unsigned int>,greater<>> que;
  d[s]=0;
  que.emplace(0,s);
  while(que.size()){
    auto [now,id]=que.top();que.pop();
    if(d[id]<now)continue;
    for(auto&[to,co]:g[id])
      if(chmin(d[to],now+co))que.emplace(d[to],to);
  }
  return d;
}

ll solve(){
  INT(n,m,s1,s2,t);
  if(n==0)exit(0);
  s1--;s2--;t--;
  WeightedGraph<ll> g(n),gg(n);
  //dsu uf(n);
  REP(_,m){
    INT(u,v);u--;v--;
    STR(s);
    ll w=(s=="x"?-1:stoi(s));
    g.add_edge(u,v,w);
    g.add_edge(v,u,w);
    gg.add_edge(u,v,max(0LL,w));
    gg.add_edge(v,u,max(0LL,w));
    //uf.merge(u,v);
  }
  //if(!uf.same(s1,t)||!uf.same(s2,t))return -1;
  ll res=1e18;

  auto dd=dijkstra(gg,t);
  chmin(res,abs(dd[s1]-dd[s2]));

  ll x=1;
  while(true){
    vector<pll> d(n,pll(LINF,0));
    d[t]={0,0};
    pqg<pll> que;
    que.emplace(0,t);
    while(que.size()){
      auto [co,id]=que.top();que.pop();
      auto [k,K]=d[id];
      if(k+K*x<co)continue;
      for(const auto&[to,we]:g[id]){
        ll b=k,B=K;
        if(~we)b+=we;
        else B++;
        auto [a,A]=d[to];
        if(a+A*x > b+B*x){
          d[to]=pll(b,B);
          que.emplace(b+B*x,to);
        }
      }
    }
    ll y=LINF;
    REP(i,n){
      auto [k,K]=d[i];
      for(const auto&[to,we]:g[i]){
        ll b=k,B=K;
        if(~we)b+=we;
        else B++;
        auto [a,A]=d[to];
        if(A<=B)continue;
        //debug(i,to,x,a,A,b,B);
        assert(x<=(b-a)/(A-B));
        assert(b>a);
        chmin(y,(b-a)/(A-B)+1);
      }
    }
    assert(y>x);
    //[x,y)
    //debug(x,y);

    auto [a,A]=d[s1];
    auto [b,B]=d[s2];

    //debug(a,A,b,B);
    
    auto f=[&](ll k){
      if(x<=k and k<y)chmin(res, abs(a-b+(A-B)*k) );
    };

    f(x);
    if(A!=B)REP(i,5) f( (b-a)/(A-B) +i-2 );

    //debug(res);
    
    if(y==LINF)break;

    f(y-1);
    x=y;
  }
  return res;
}

int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  while(true)cout<<solve()<<"\n";
}
accuracy: 1
time_ms: 320
memory_kb: 3632
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

template <typename T>
class ConvexHullTrick {
public:
    explicit ConvexHullTrick(bool monotone_query = false) : monotone_query(monotone_query) {}

    void add(T a, T b) {
        Line line(a, b);
        while (lines.size() >= 2 && check(*(lines.end() - 2), lines.back(), line)) {
            lines.pop_back();
        }
        lines.push_back(line);
    }

    T get(T x) {
        if (monotone_query) {
            while (lines.size() - head >= 2 && lines[head](x) > lines[head + 1](x)) {
                ++head;
            }
            return lines[head](x);
        } else {
            int lb = -1, ub = lines.size() - 1;
            while (ub - lb > 1) {
                int m = (lb + ub) / 2;
                if (lines[m](x) > lines[m + 1](x)) {
                    lb = m;
                } else {
                    ub = m;
                }
            }
            return lines[ub](x);
        }
    }

private:
    struct Line {
        T a, b;
        Line(T a, T b) : a(a), b(b) {}
        T operator()(T x) const { return a * x + b; }
    };

    std::vector<Line> lines;
    bool monotone_query;
    int head = 0;

    static bool check(Line l1, Line l2, Line l3) {
        if (l2.a == l3.a) return l2.b >= l3.b;
        return 1.0 * (l2.b - l1.b) / (l2.a - l1.a) <= 1.0 * (l3.b - l2.b) / (l3.a - l2.a);
    }
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    constexpr ll INF = 1e18;
    const int X = 100;

    while (true) {
        int N, M, S1, S2, T;
        cin >> N >> M >> S1 >> S2 >> T;
        if (N == 0) break;
        --S1, --S2, --T;
        vector<vector<pair<int, ll>>> G(N);
        rep(_,0,M) {
            int a, b;
            string w;
            cin >> a >> b >> w;
            --a, --b;
            ll c;
            if (w == "x") {
                c = -1;
            } else {
                c = stoi(w);
            }
            G[a].push_back({b, c});
            G[b].push_back({a, c});
        }

        vector<vector<ll>> dist(N, vector<ll>(X+1, INF));
        dist[T][0] = 0;
        using P = tuple<ll, int, int>;
        priority_queue<P, vector<P>, greater<>> pq;
        pq.push({0, T, 0});

        while (!pq.empty()) {
            auto [d, v, a] = pq.top();
            pq.pop();
            if (dist[v][a] < d) continue;
            for (auto [u, w] : G[v]) {
                if (w == -1) {
                    if (a < X && dist[u][a+1] > d) {
                        dist[u][a+1] = d;
                        pq.push({d, u, a+1});
                    }
                } else {
                    if (dist[u][a] > d+w) {
                        dist[u][a] = d+w;
                        pq.push({d+w, u, a});
                    }
                }
            }
        }

        ConvexHullTrick<ll> cht1(true), cht2(true);

        revrep(i,X+1,0) {
            if (dist[S1][i] < INF) cht1.add(i, dist[S1][i]);
            if (dist[S2][i] < INF) cht2.add(i, dist[S2][i]);
        }

        vector<ll> check = {0};
        rep(i,0,X+1) rep(j,i+1,X+1) {
            if (dist[S1][i] < INF && dist[S1][j] < INF) {
                ll x = 1.0 * (dist[S1][i] - dist[S1][j]) / (j - i);
                if (x >= 0) {
                    check.push_back(x);
                    check.push_back(x+1);
                }
            }
            if (dist[S2][i] < INF && dist[S2][j] < INF) {
                ll x = 1.0 * (dist[S2][i] - dist[S2][j]) / (j - i);
                if (x >= 0) {
                    check.push_back(x);
                    check.push_back(x+1);
                }
            }
            if (dist[S1][i] < INF && dist[S2][j] < INF) {
                ll x = 1.0 * (dist[S1][i] - dist[S2][j]) / (j - i);
                if (x >= 0) {
                    check.push_back(x);
                    check.push_back(x+1);
                }
            }
            if (dist[S2][i] < INF && dist[S1][j] < INF) {
                ll x = 1.0 * (dist[S2][i] - dist[S1][j]) / (j - i);
                if (x >= 0) {
                    check.push_back(x);
                    check.push_back(x+1);
                }
            }
        }
        sort(all(check));
        check.erase(unique(all(check)), check.end());

        ll ans = 1e18;
        for (ll x : check) {
            chmin(ans, abs(cht1.get(x) - cht2.get(x)));
        }

        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 300
memory_kb: 5920
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

template <typename T>
class ConvexHullTrick {
public:
    explicit ConvexHullTrick(bool monotone_query = false) : monotone_query(monotone_query) {}

    void add(T a, T b) {
        Line line(a, b);
        while (lines.size() >= 2 && check(*(lines.end() - 2), lines.back(), line)) {
            lines.pop_back();
        }
        lines.push_back(line);
    }

    T get(T x) {
        if (monotone_query) {
            while (lines.size() - head >= 2 && lines[head](x) > lines[head + 1](x)) {
                ++head;
            }
            return lines[head](x);
        } else {
            int lb = -1, ub = lines.size() - 1;
            while (ub - lb > 1) {
                int m = (lb + ub) / 2;
                if (lines[m](x) > lines[m + 1](x)) {
                    lb = m;
                } else {
                    ub = m;
                }
            }
            return lines[ub](x);
        }
    }

private:
    struct Line {
        T a, b;
        Line(T a, T b) : a(a), b(b) {}
        T operator()(T x) const { return a * x + b; }
    };

    std::vector<Line> lines;
    bool monotone_query;
    int head = 0;

    static bool check(Line l1, Line l2, Line l3) {
        if (l2.a == l3.a) return l2.b >= l3.b;
        return 1.0 * (l2.b - l1.b) / (l2.a - l1.a) <= 1.0 * (l3.b - l2.b) / (l3.a - l2.a);
    }
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    constexpr ll INF = 1e18;
    const int X = 100;

    while (true) {
        int N, M, S1, S2, T;
        cin >> N >> M >> S1 >> S2 >> T;
        if (N == 0) break;
        --S1, --S2, --T;
        vector<vector<pair<int, ll>>> G(N);
        rep(_,0,M) {
            int a, b;
            string w;
            cin >> a >> b >> w;
            --a, --b;
            ll c;
            if (w == "x") {
                c = -1;
            } else {
                c = stoi(w);
            }
            G[a].push_back({b, c});
            G[b].push_back({a, c});
        }

        vector<vector<ll>> dist(N, vector<ll>(X+1, INF));
        dist[T][0] = 0;
        using P = tuple<ll, int, int>;
        priority_queue<P, vector<P>, greater<>> pq;
        pq.push({0, T, 0});

        while (!pq.empty()) {
            auto [d, v, a] = pq.top();
            pq.pop();
            if (dist[v][a] < d) continue;
            for (auto [u, w] : G[v]) {
                if (w == -1) {
                    if (a < X && dist[u][a+1] > d) {
                        dist[u][a+1] = d;
                        pq.push({d, u, a+1});
                    }
                } else {
                    if (dist[u][a] > d+w) {
                        dist[u][a] = d+w;
                        pq.push({d+w, u, a});
                    }
                }
            }
        }

        ConvexHullTrick<ll> cht1(true), cht2(true);

        revrep(i,X+1,0) {
            if (dist[S1][i] < INF) cht1.add(i, dist[S1][i]);
            if (dist[S2][i] < INF) cht2.add(i, dist[S2][i]);
        }

        vector<ll> check = {0};
        rep(i,0,X+1) rep(j,i+1,X+1) {
            if (dist[S1][i] < INF && dist[S1][j] < INF) {
                ll x = 1.0 * (dist[S1][i] - dist[S1][j]) / (j - i);
                rep(d,-5,5) {
                    if (x+d >= 0) check.push_back(x+d);
                }
            }
            if (dist[S2][i] < INF && dist[S2][j] < INF) {
                ll x = 1.0 * (dist[S2][i] - dist[S2][j]) / (j - i);
                rep(d,-5,5) {
                    if (x+d >= 0) check.push_back(x+d);
                }
            }
            if (dist[S1][i] < INF && dist[S2][j] < INF) {
                ll x = 1.0 * (dist[S1][i] - dist[S2][j]) / (j - i);
                rep(d,-5,5) {
                    if (x+d >= 0) check.push_back(x+d);
                }
            }
            if (dist[S2][i] < INF && dist[S1][j] < INF) {
                ll x = 1.0 * (dist[S2][i] - dist[S1][j]) / (j - i);
                rep(d,-5,5) {
                    if (x+d >= 0) check.push_back(x+d);
                }
            }
        }
        sort(all(check));
        check.erase(unique(all(check)), check.end());

        ll ans = 1e18;
        for (ll x : check) {
            chmin(ans, abs(cht1.get(x) - cht2.get(x)));
        }

        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 620
memory_kb: 7604
final_rank: 15

code_snippet: #include <bits/stdc++.h>

#ifdef _MSC_VER
#  include <intrin.h>
#else
#  include <x86intrin.h>
#endif

#include <limits>
#include <type_traits>

namespace suisen {
// ! utility
template <typename ...Types>
using constraints_t = std::enable_if_t<std::conjunction_v<Types...>, std::nullptr_t>;
template <bool cond_v, typename Then, typename OrElse>
constexpr decltype(auto) constexpr_if(Then&& then, OrElse&& or_else) {
    if constexpr (cond_v) {
        return std::forward<Then>(then);
    } else {
        return std::forward<OrElse>(or_else);
    }
}

// ! function
template <typename ReturnType, typename Callable, typename ...Args>
using is_same_as_invoke_result = std::is_same<std::invoke_result_t<Callable, Args...>, ReturnType>;
template <typename F, typename T>
using is_uni_op = is_same_as_invoke_result<T, F, T>;
template <typename F, typename T>
using is_bin_op = is_same_as_invoke_result<T, F, T, T>;

template <typename Comparator, typename T>
using is_comparator = std::is_same<std::invoke_result_t<Comparator, T, T>, bool>;

// ! integral
template <typename T, typename = constraints_t<std::is_integral<T>>>
constexpr int bit_num = std::numeric_limits<std::make_unsigned_t<T>>::digits;
template <typename T, unsigned int n>
struct is_nbit { static constexpr bool value = bit_num<T> == n; };
template <typename T, unsigned int n>
static constexpr bool is_nbit_v = is_nbit<T, n>::value;

// ?
template <typename T>
struct safely_multipliable {};
template <>
struct safely_multipliable<int> { using type = long long; };
template <>
struct safely_multipliable<long long> { using type = __int128_t; };
template <>
struct safely_multipliable<unsigned int> { using type = unsigned long long; };
template <>
struct safely_multipliable<unsigned long int> { using type = __uint128_t; };
template <>
struct safely_multipliable<unsigned long long> { using type = __uint128_t; };
template <>
struct safely_multipliable<float> { using type = float; };
template <>
struct safely_multipliable<double> { using type = double; };
template <>
struct safely_multipliable<long double> { using type = long double; };
template <typename T>
using safely_multipliable_t = typename safely_multipliable<T>::type;

template <typename T, typename = void>
struct rec_value_type {
    using type = T;
};
template <typename T>
struct rec_value_type<T, std::void_t<typename T::value_type>> {
    using type = typename rec_value_type<typename T::value_type>::type;
};
template <typename T>
using rec_value_type_t = typename rec_value_type<T>::type;

} // namespace suisen

// ! type aliases
using i128 = __int128_t;
using u128 = __uint128_t;

template <typename T>
using pq_greater = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <typename T, typename U>
using umap = std::unordered_map<T, U>;

// ! macros (capital: internal macro)
#define OVERLOAD2(_1,_2,name,...) name
#define OVERLOAD3(_1,_2,_3,name,...) name
#define OVERLOAD4(_1,_2,_3,_4,name,...) name

#define REP4(i,l,r,s)  for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l);i<(r);i+=(s))
#define REP3(i,l,r)    REP4(i,l,r,1)
#define REP2(i,n)      REP3(i,0,n)
#define REPINF3(i,l,s) for(std::remove_reference_t<std::remove_const_t<decltype(l)>>i=(l);;i+=(s))
#define REPINF2(i,l)   REPINF3(i,l,1)
#define REPINF1(i)     REPINF2(i,0)
#define RREP4(i,l,r,s) for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l)+fld((r)-(l)-1,s)*(s);i>=(l);i-=(s))
#define RREP3(i,l,r)   RREP4(i,l,r,1)
#define RREP2(i,n)     RREP3(i,0,n)

#define rep(...)    OVERLOAD4(__VA_ARGS__, REP4   , REP3   , REP2   )(__VA_ARGS__)
#define rrep(...)   OVERLOAD4(__VA_ARGS__, RREP4  , RREP3  , RREP2  )(__VA_ARGS__)
#define repinf(...) OVERLOAD3(__VA_ARGS__, REPINF3, REPINF2, REPINF1)(__VA_ARGS__)

#define CAT_I(a, b) a##b
#define CAT(a, b) CAT_I(a, b)
#define UNIQVAR(tag) CAT(tag, __LINE__)
#define loop(n) for (std::remove_reference_t<std::remove_const_t<decltype(n)>> UNIQVAR(loop_variable) = n; UNIQVAR(loop_variable) --> 0;)

#define all(iterable) std::begin(iterable), std::end(iterable)
#define input(type, ...) type __VA_ARGS__; read(__VA_ARGS__)

#ifdef LOCAL
#  define debug(...) debug_internal(#__VA_ARGS__, __VA_ARGS__)

template <class T, class... Args>
void debug_internal(const char* s, T&& first, Args&&... args) {
    constexpr const char* prefix = "[\033[32mDEBUG\033[m] ";
    constexpr const char* open_brakets = sizeof...(args) == 0 ? "" : "(";
    constexpr const char* close_brakets = sizeof...(args) == 0 ? "" : ")";
    std::cerr << prefix << open_brakets << s << close_brakets << ": " << open_brakets << std::forward<T>(first);
    ((std::cerr << ", " << std::forward<Args>(args)), ...);
    std::cerr << close_brakets << "\n";
}

#else
#  define debug(...) void(0)
#endif

// ! I/O utilities

// __int128_t
std::ostream& operator<<(std::ostream& dest, __int128_t value) {
    std::ostream::sentry s(dest);
    if (s) {
        __uint128_t tmp = value < 0 ? -value : value;
        char buffer[128];
        char* d = std::end(buffer);
        do {
            --d;
            *d = "0123456789"[tmp % 10];
            tmp /= 10;
        } while (tmp != 0);
        if (value < 0) {
            --d;
            *d = '-';
        }
        int len = std::end(buffer) - d;
        if (dest.rdbuf()->sputn(d, len) != len) {
            dest.setstate(std::ios_base::badbit);
        }
    }
    return dest;
}
// __uint128_t
std::ostream& operator<<(std::ostream& dest, __uint128_t value) {
    std::ostream::sentry s(dest);
    if (s) {
        char buffer[128];
        char* d = std::end(buffer);
        do {
            --d;
            *d = "0123456789"[value % 10];
            value /= 10;
        } while (value != 0);
        int len = std::end(buffer) - d;
        if (dest.rdbuf()->sputn(d, len) != len) {
            dest.setstate(std::ios_base::badbit);
        }
    }
    return dest;
}

// pair
template <typename T, typename U>
std::ostream& operator<<(std::ostream& out, const std::pair<T, U>& a) {
    return out << a.first << ' ' << a.second;
}
// tuple
template <unsigned int N = 0, typename ...Args>
std::ostream& operator<<(std::ostream& out, const std::tuple<Args...>& a) {
    if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) {
        return out;
    } else {
        out << std::get<N>(a);
        if constexpr (N + 1 < std::tuple_size_v<std::tuple<Args...>>) {
            out << ' ';
        }
        return operator<<<N + 1>(out, a);
    }
}
// vector
template <typename T>
std::ostream& operator<<(std::ostream& out, const std::vector<T>& a) {
    for (auto it = a.begin(); it != a.end();) {
        out << *it;
        if (++it != a.end()) out << ' ';
    }
    return out;
}
// array
template <typename T, size_t N>
std::ostream& operator<<(std::ostream& out, const std::array<T, N>& a) {
    for (auto it = a.begin(); it != a.end();) {
        out << *it;
        if (++it != a.end()) out << ' ';
    }
    return out;
}
inline void print() { std::cout << '\n'; }
template <typename Head, typename... Tail>
inline void print(const Head& head, const Tail &...tails) {
    std::cout << head;
    if (sizeof...(tails)) std::cout << ' ';
    print(tails...);
}
template <typename Iterable>
auto print_all(const Iterable& v, std::string sep = " ", std::string end = "\n") -> decltype(std::cout << *v.begin(), void()) {
    for (auto it = v.begin(); it != v.end();) {
        std::cout << *it;
        if (++it != v.end()) std::cout << sep;
    }
    std::cout << end;
}

__int128_t parse_i128(std::string& s) {
    __int128_t ret = 0;
    for (int i = 0; i < int(s.size()); i++) if ('0' <= s[i] and s[i] <= '9') ret = 10 * ret + s[i] - '0';
    if (s[0] == '-') ret = -ret;
    return ret;
}
__uint128_t parse_u128(std::string& s) {
    __uint128_t ret = 0;
    for (int i = 0; i < int(s.size()); i++) if ('0' <= s[i] and s[i] <= '9') ret = 10 * ret + s[i] - '0';
    return ret;
}
// __int128_t
std::istream& operator>>(std::istream& in, __int128_t& v) {
    std::string s;
    in >> s;
    v = parse_i128(s);
    return in;
}
// __uint128_t
std::istream& operator>>(std::istream& in, __uint128_t& v) {
    std::string s;
    in >> s;
    v = parse_u128(s);
    return in;
}
// pair
template <typename T, typename U>
std::istream& operator>>(std::istream& in, std::pair<T, U>& a) {
    return in >> a.first >> a.second;
}
// tuple
template <unsigned int N = 0, typename ...Args>
std::istream& operator>>(std::istream& in, std::tuple<Args...>& a) {
    if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) {
        return in;
    } else {
        return operator>><N + 1>(in >> std::get<N>(a), a);
    }
}
// vector
template <typename T>
std::istream& operator>>(std::istream& in, std::vector<T>& a) {
    for (auto it = a.begin(); it != a.end(); ++it) in >> *it;
    return in;
}
// array
template <typename T, size_t N>
std::istream& operator>>(std::istream& in, std::array<T, N>& a) {
    for (auto it = a.begin(); it != a.end(); ++it) in >> *it;
    return in;
}
template <typename ...Args>
void read(Args &...args) {
    (std::cin >> ... >> args);
}

// ! integral utilities

// Returns pow(-1, n)
template <typename T>
constexpr inline int pow_m1(T n) {
    return -(n & 1) | 1;
}
// Returns pow(-1, n)
template <>
constexpr inline int pow_m1<bool>(bool n) {
    return -int(n) | 1;
}

// Returns floor(x / y)
template <typename T>
constexpr inline T fld(const T x, const T y) {
    return (x ^ y) >= 0 ? x / y : (x - (y + pow_m1(y >= 0))) / y;
}
template <typename T>
constexpr inline T cld(const T x, const T y) {
    return (x ^ y) <= 0 ? x / y : (x + (y + pow_m1(y >= 0))) / y;
}

template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
__attribute__((target("popcnt"))) constexpr inline int popcount(const T x) { return _mm_popcnt_u32(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
__attribute__((target("popcnt"))) constexpr inline int popcount(const T x) { return _mm_popcnt_u32(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
__attribute__((target("popcnt"))) constexpr inline int popcount(const T x) { return _mm_popcnt_u64(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clzll(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctzll(x) : suisen::bit_num<T>; }
template <typename T>
constexpr inline int floor_log2(const T x) { return suisen::bit_num<T> -1 - count_lz(x); }
template <typename T>
constexpr inline int ceil_log2(const T x) { return floor_log2(x) + ((x & -x) != x); }
template <typename T>
constexpr inline int kth_bit(const T x, const unsigned int k) { return (x >> k) & 1; }
template <typename T>
constexpr inline int parity(const T x) { return popcount(x) & 1; }

// ! container

template <typename T, typename Comparator, suisen::constraints_t<suisen::is_comparator<Comparator, T>> = nullptr>
auto priqueue_comp(const Comparator comparator) {
    return std::priority_queue<T, std::vector<T>, Comparator>(comparator);
}

template <typename Iterable>
auto isize(const Iterable& iterable) -> decltype(int(iterable.size())) {
    return iterable.size();
}

template <typename T, typename Gen, suisen::constraints_t<suisen::is_same_as_invoke_result<T, Gen, int>> = nullptr>
auto generate_vector(int n, Gen generator) {
    std::vector<T> v(n);
    for (int i = 0; i < n; ++i) v[i] = generator(i);
    return v;
}
template <typename T>
auto generate_range_vector(T l, T r) {
    return generate_vector(r - l, [l](int i) { return l + i; });
}
template <typename T>
auto generate_range_vector(T n) {
    return generate_range_vector(0, n);
}

template <typename T>
void sort_unique_erase(std::vector<T>& a) {
    std::sort(a.begin(), a.end());
    a.erase(std::unique(a.begin(), a.end()), a.end());
}

template <typename InputIterator, typename BiConsumer>
auto foreach_adjacent_values(InputIterator first, InputIterator last, BiConsumer f) -> decltype(f(*first++, *last), void()) {
    if (first != last) for (auto itr = first, itl = itr++; itr != last; itl = itr++) f(*itl, *itr);
}
template <typename Container, typename BiConsumer>
auto foreach_adjacent_values(Container c, BiConsumer f) -> decltype(c.begin(), c.end(), void()) {
    foreach_adjacent_values(c.begin(), c.end(), f);
}

// ! other utilities

// x <- min(x, y). returns true iff `x` has chenged.
template <typename T>
inline bool chmin(T& x, const T& y) {
    if (y >= x) return false;
    x = y;
    return true;
}
// x <- max(x, y). returns true iff `x` has chenged.
template <typename T>
inline bool chmax(T& x, const T& y) {
    if (y <= x) return false;
    x = y;
    return true;
}

template <typename T, std::enable_if_t<std::is_integral_v<T>, std::nullptr_t> = nullptr>
std::string bin(T val, int bit_num = -1) {
    std::string res;
    if (bit_num >= 0) {
        for (int bit = bit_num; bit-- > 0;) res += '0' + ((val >> bit) & 1);
    } else {
        for (; val; val >>= 1) res += '0' + (val & 1);
        std::reverse(res.begin(), res.end());
    }
    return res;
}

template <typename T, std::enable_if_t<std::is_integral_v<T>, std::nullptr_t> = nullptr>
std::vector<T> digits_low_to_high(T val, T base = 10) {
    std::vector<T> res;
    for (; val; val /= base) res.push_back(val % base);
    if (res.empty()) res.push_back(T{ 0 });
    return res;
}
template <typename T, std::enable_if_t<std::is_integral_v<T>, std::nullptr_t> = nullptr>
std::vector<T> digits_high_to_low(T val, T base = 10) {
    auto res = digits_low_to_high(val, base);
    std::reverse(res.begin(), res.end());
    return res;
}

template <typename T>
std::string join(const std::vector<T>& v, const std::string& sep, const std::string& end) {
    std::ostringstream ss;
    for (auto it = v.begin(); it != v.end();) {
        ss << *it;
        if (++it != v.end()) ss << sep;
    }
    ss << end;
    return ss.str();
}

namespace suisen {}
using namespace suisen;
using namespace std;

struct io_setup {
    io_setup(int precision = 20) {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(precision);
    }
} io_setup_{};

// ! code from here

constexpr long long inf = numeric_limits<long long>::max() / 200;

void solve() {
    input(int, n, m, s1, s2, t);
    --s1, --s2, --t;
    if (n == 0) exit(0);

    int k = 0;
    vector<vector<pair<int, long long>>> g(n);
    rep(i, m) {
        input(int, a, b);
        --a, --b;
        input(string, ws);
        if (ws[0] == 'x') {
            g[a].emplace_back(b, -1);
            g[b].emplace_back(a, -1);
            ++k;
        } else {
            int w = stoi(ws);
            g[a].emplace_back(b, w);
            g[b].emplace_back(a, w);
        }
    }

    vector<vector<long long>> d(k + 1, vector<long long>(n, inf));
    pq_greater<tuple<long long, int, int>> pq;
    pq.emplace(d[0][t] = 0, 0, t);

    while (pq.size()) {
        auto [dpu, p, u] = pq.top();
        pq.pop();
        if (d[p][u] != dpu) continue;
        for (auto [v, w] : g[u]) {
            if (w == -1) {
                if (p != k and chmin(d[p + 1][v], dpu)) {
                    pq.emplace(d[p + 1][v], p + 1, v);
                }
            } else {
                if (chmin(d[p][v], dpu + w)) {
                    pq.emplace(d[p][v], p, v);
                }
            }
        }
    }

    long long ans = inf;
    if (d[0][s1] != inf and d[0][s2] != inf) {
        chmin(ans, abs(d[0][s1] - d[0][s2]));
    }
    rep(i, k + 1) rep(j, i) {
        for (int s : { s1, s2 }) {
            long long ci = d[i][s]; // i * x + ci
            long long cj = d[j][s]; // j * x + cj
            if (ci == inf or cj == inf) continue;
            long long xl = max(0LL, fld(cj - ci, (long long) i - j));
            for (long long x : { xl, xl + 1 }) {
                long long d1 = inf, d2 = inf;
                rep(v, k + 1) {
                    chmin(d1, d[v][s1] + v * x);
                    chmin(d2, d[v][s2] + v * x);
                }
                if (d1 != inf and d2 != inf) {
                    chmin(ans, abs(d1 - d2));
                }
            }
        }
    }
    rep(i, k + 1) rep(j, k + 1) if (i != j) {
        long long ci = d[i][s1]; // i * x + ci
        long long cj = d[j][s2]; // j * x + cj
        if (ci == inf or cj == inf) continue;
        long long xl = max(0LL, fld(cj - ci, (long long) i - j));
        for (long long x : { xl, xl + 1 }) {
            long long d1 = inf, d2 = inf;
            rep(v, k + 1) {
                chmin(d1, d[v][s1] + v * x);
                chmin(d2, d[v][s2] + v * x);
            }
            if (d1 != inf and d2 != inf) {
                chmin(ans, abs(d1 - d2));
            }
        }
    }
    long long d1 = inf, d2 = inf;
    rep(v, k + 1) {
        chmin(d1, d[v][s1]);
        chmin(d2, d[v][s2]);
    }
    if (d1 != inf and d2 != inf) {
        chmin(ans, abs(d1 - d2));
    }
    print(ans);
}

int main() {
    while (true) solve();
    return 0;
}
accuracy: 1
time_ms: 350
memory_kb: 5804
final_rank: 7

code_snippet: /*	author:  Kite_kuma
	created: 2022.03.01 18:07:17 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region graph

struct Edge {
	int to;
	long long cost;
	Edge() = default;
	Edge(int to_, long long cost_) : to(to_), cost(cost_) {}
	bool operator<(const Edge &a) const { return cost < a.cost; }
	bool operator>(const Edge &a) const { return cost > a.cost; }
	friend std::ostream &operator<<(std::ostream &s, Edge &a) {
		s << "to: " << a.to << ", cost: " << a.cost;
		return s;
	}
};

class Graph {
	std::vector<std::vector<Edge>> edges;

   public:
	inline const std::vector<Edge> &operator[](int k) const { return edges[k]; }
	inline std::vector<Edge> &operator[](int k) { return edges[k]; }

	int size() const { return edges.size(); }
	void resize(const int n) { edges.resize(n); }

	Graph() = default;
	Graph(int n) : edges(n) {}
	Graph(int n, int e, bool weight = 0, bool directed = 0, int idx = 1) : edges(n) { input(e, weight, directed, idx); }
	const long long INF = 3e18;

	void input(int e = -1, bool weight = 0, bool directed = false, int idx = 1) {
		if(e == -1) e = size() - 1;
		while(e--) {
			int u, v;
			long long cost = 1;
			std::cin >> u >> v;
			if(weight) std::cin >> cost;
			u -= idx, v -= idx;
			edges[u].emplace_back(v, cost);
			if(!directed) edges[v].emplace_back(u, cost);
		}
	}

	void add_edge(int u, int v, long long cost = 1, bool directed = false, int idx = 0) {
		u -= idx, v -= idx;
		edges[u].emplace_back(v, cost);
		if(!directed) edges[v].emplace_back(u, cost);
	}

	// Ο(V+E)
	std::vector<long long> bfs(int s) {
		std::vector<long long> dist(size(), INF);
		std::queue<int> que;
		dist[s] = 0;
		que.push(s);
		while(!que.empty()) {
			int v = que.front();
			que.pop();
			for(auto &e : edges[v]) {
				if(dist[e.to] != INF) continue;
				dist[e.to] = dist[v] + e.cost;
				que.push(e.to);
			}
		}
		return dist;
	}

	// Ο(V+E)
	// constraint: cost of each edge is zero or one
	std::vector<long long> zero_one_bfs(int s) {
		std::vector<long long> dist(size(), INF);
		std::deque<int> deq;
		dist[s] = 0;
		deq.push_back(s);
		while(!deq.empty()) {
			int v = deq.front();
			deq.pop_front();
			for(auto &e : edges[v]) {
				assert(0LL <= e.cost and e.cost < 2LL);
				if(e.cost and dist[e.to] > dist[v] + 1) {
					dist[e.to] = dist[v] + 1;
					deq.push_back(e.to);
				} else if(!e.cost and dist[e.to] > dist[v]) {
					dist[e.to] = dist[v];
					deq.push_front(e.to);
				}
			}
		}
		return dist;
	}

	// Ο((E+V)logV)
	// cannot reach: INF
	std::vector<long long> dijkstra(int s) {  // verified
		std::vector<long long> dist(size(), INF);
		const auto compare = [](const std::pair<long long, int> &a, const std::pair<long long, int> &b) { return a.first > b.first; };
		std::priority_queue<std::pair<long long, int>, std::vector<std::pair<long long, int>>, decltype(compare)> que{compare};
		dist[s] = 0;
		que.emplace(0, s);
		while(!que.empty()) {
			std::pair<long long, int> p = que.top();
			que.pop();
			int v = p.second;
			if(dist[v] < p.first) continue;
			for(auto &e : edges[v]) {
				if(dist[e.to] > dist[v] + e.cost) {
					dist[e.to] = dist[v] + e.cost;
					que.emplace(dist[e.to], e.to);
				}
			}
		}
		return dist;
	}

	// Ο(VE)
	// cannot reach: INF
	// negative cycle: -INF
	std::vector<long long> bellman_ford(int s) {  // verified
		int n = size();
		std::vector<long long> res(n, INF);
		res[s] = 0;
		for(int loop = 0; loop < n - 1; loop++) {
			for(int v = 0; v < n; v++) {
				if(res[v] == INF) continue;
				for(auto &e : edges[v]) {
					res[e.to] = std::min(res[e.to], res[v] + e.cost);
				}
			}
		}
		std::queue<int> que;
		std::vector<int> chk(n);
		for(int v = 0; v < n; v++) {
			if(res[v] == INF) continue;
			for(auto &e : edges[v]) {
				if(res[e.to] > res[v] + e.cost and !chk[e.to]) {
					que.push(e.to);
					chk[e.to] = 1;
				}
			}
		}
		while(!que.empty()) {
			int now = que.front();
			que.pop();
			for(auto &e : edges[now]) {
				if(!chk[e.to]) {
					chk[e.to] = 1;
					que.push(e.to);
				}
			}
		}
		for(int i = 0; i < n; i++)
			if(chk[i]) res[i] = -INF;
		return res;
	}

	// Ο(V^3)
	std::vector<std::vector<long long>> warshall_floyd() {	// verified
		int n = size();
		std::vector<std::vector<long long>> dist(n, std::vector<long long>(n, INF));
		for(int i = 0; i < n; i++) dist[i][i] = 0;
		for(int i = 0; i < n; i++)
			for(auto &e : edges[i]) dist[i][e.to] = std::min(dist[i][e.to], e.cost);
		for(int k = 0; k < n; k++)
			for(int i = 0; i < n; i++) {
				if(dist[i][k] == INF) continue;
				for(int j = 0; j < n; j++) {
					if(dist[k][j] == INF) continue;
					dist[i][j] = std::min(dist[i][j], dist[i][k] + dist[k][j]);
				}
			}
		return dist;
	}

	// Ο(V) (using DFS)
	// if a directed cycle exists, return {}
	std::vector<int> topological_sort() {  // verified
		std::vector<int> res;
		int n = size();
		std::vector<int> used(n, 0);
		bool not_DAG = false;
		auto dfs = [&](auto self, int k) -> void {
			if(not_DAG) return;
			if(used[k]) {
				if(used[k] == 1) not_DAG = true;
				return;
			}
			used[k] = 1;
			for(auto &e : edges[k]) self(self, e.to);
			used[k] = 2;
			res.push_back(k);
		};
		for(int i = 0; i < n; i++) dfs(dfs, i);
		if(not_DAG) return std::vector<int>{};
		std::reverse(res.begin(), res.end());
		return res;
	}

	bool is_DAG() { return !topological_sort().empty(); }  // verified

	// Ο(V)
	// array of the distance from each vertex to the most distant vertex
	std::vector<long long> height() {  // verified
		auto vec1 = bfs(0);
		int v1 = -1, v2 = -1;
		long long dia = -1;
		for(int i = 0; i < int(size()); i++)
			if(dia < vec1[i]) dia = vec1[i], v1 = i;
		vec1 = bfs(v1);
		dia = -1;
		for(int i = 0; i < int(size()); i++)
			if(dia < vec1[i]) dia = vec1[i], v2 = i;
		auto vec2 = bfs(v2);
		for(int i = 0; i < int(size()); i++) {
			if(vec1[i] < vec2[i]) vec1[i] = vec2[i];
		}
		return vec1;
	}

	// O(V+E)
	// vector<(int)(0 or 1)>
	// if it is not bipartite, return {}
	std::vector<int> bipartite_grouping() {
		std::vector<int> colors(size(), -1);
		auto dfs = [&](auto self, int now, int col) -> bool {
			colors[now] = col;
			for(auto &e : edges[now]) {
				if(col == colors[e.to]) return false;
				if(colors[e.to] == -1 and !self(self, e.to, !col)) return false;
			}
			return true;
		};
		for(int i = 0; i < int(size()); i++)
			if(!colors[i] and !dfs(dfs, i, 0)) return std::vector<int>{};
		return colors;
	}

	bool is_bipartite() { return !bipartite_grouping().empty(); }

	// Ο(V+E)
	// ((v1, v2), diameter)
	std::pair<std::pair<int, int>, long long> diameter() {	// verified
		auto vec = bfs(0);
		int v1 = -1, v2 = -1;
		long long dia = -1;
		for(int i = 0; i < int(size()); i++)
			if(dia < vec[i]) dia = vec[i], v1 = i;
		vec = bfs(v1);
		dia = -1;
		for(int i = 0; i < int(size()); i++)
			if(dia < vec[i]) dia = vec[i], v2 = i;
		std::pair<std::pair<int, int>, long long> res = {{v1, v2}, dia};
		return res;
	}

	// Ο(ElogV)
	long long prim() {	// verified
		long long res = 0;
		std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>> que;
		for(auto &e : edges[0]) que.push(e);
		std::vector<int> chk(size());
		chk[0] = 1;
		int cnt = 1;
		while(cnt < size()) {
			auto e = que.top();
			que.pop();
			if(chk[e.to]) continue;
			cnt++;
			res += e.cost;
			chk[e.to] = 1;
			for(auto &e2 : edges[e.to]) que.push(e2);
		}
		return res;
	}

	// Ο(ElogE)
	long long kruskal() {  // verified
		std::vector<std::tuple<int, int, long long>> Edges;
		for(int i = 0; i < int(size()); i++)
			for(auto &e : edges[i]) Edges.emplace_back(i, e.to, e.cost);
		std::sort(Edges.begin(), Edges.end(), [](const std::tuple<int, int, long long> &a, const std::tuple<int, int, long long> &b) {
			return std::get<2>(a) < std::get<2>(b);
		});
		std::vector<int> uf_data(size(), -1);
		auto root = [&uf_data](auto self, int x) -> int {
			if(uf_data[x] < 0) return x;
			return uf_data[x] = self(self, uf_data[x]);
		};
		auto unite = [&uf_data, &root](int u, int v) -> bool {
			u = root(root, u), v = root(root, v);
			if(u == v) return false;
			if(uf_data[u] > uf_data[v]) std::swap(u, v);
			uf_data[u] += uf_data[v];
			uf_data[v] = u;
			return true;
		};
		long long ret = 0;
		for(auto &e : Edges)
			if(unite(std::get<0>(e), std::get<1>(e))) ret += std::get<2>(e);
		return ret;
	}

	// O(V)
	std::vector<int> centroid() {
		int n = size();
		std::vector<int> centroid, sz(n);
		auto dfs = [&](auto self, int now, int per) -> void {
			sz[now] = 1;
			bool is_centroid = true;
			for(auto &e : edges[now]) {
				if(e.to != per) {
					self(self, e.to, now);
					sz[now] += sz[e.to];
					if(sz[e.to] > n / 2) is_centroid = false;
				}
			}
			if(n - sz[now] > n / 2) is_centroid = false;
			if(is_centroid) centroid.push_back(now);
		};
		dfs(dfs, 0, -1);
		return centroid;
	}

	// Ο(V+E)
	// directed graph from root to leaf
	Graph root_to_leaf(int root = 0) {
		Graph res(size());
		std::vector<int> chk(size(), 0);
		chk[root] = 1;
		auto dfs = [&](auto self, int now) -> void {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				res.add_edge(now, e.to, e.cost, 1, 0);
				self(self, e.to);
			}
		};
		dfs(dfs, root);
		return res;
	}

	// Ο(V+E)
	// directed graph from leaf to root
	Graph leaf_to_root(int root = 0) {
		Graph res(size());
		std::vector<int> chk(size(), 0);
		chk[root] = 1;
		auto dfs = [&](auto self, int now) -> void {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				res.add_edge(e.to, now, e.cost, 1, 0);
				self(self, e.to);
			}
		};
		dfs(dfs, root);
		return res;
	}

	// long long Chu_Liu_Edmonds(int root = 0) {}
};

#pragma endregion

ll solve(int n) {
	int m;
	cin >> m;
	int s2, s1, t;
	cin >> s1 >> s2 >> t;
	t--;
	s1--;
	s2--;

	debug(n, m, s1, s2, t);

	const int bridge_max = 105;
	vector<vi> id(bridge_max, vi(n));
	int gs = 0;
	foa(v, id) foa(c, v) c = gs++;
	Graph g(gs);

	rep(m) {
		int a, b;
		cin >> a >> b;
		--a;
		--b;
		string w;
		cin >> w;
		debug(a, b, w);
		if(w == "x") {
			rep(bf, bridge_max - 1) {
				g.add_edge(id[bf][a], id[bf + 1][b], 0LL, true, 0);
				g.add_edge(id[bf][b], id[bf + 1][a], 0LL, true, 0);
			}
		} else {
			ll cost = stoll(w);
			rep(bf, bridge_max) { g.add_edge(id[bf][a], id[bf][b], cost, false, 0); }
		}
	}

	rep(i, bridge_max - 1) rep(j, n) { g.add_edge(id[i][j], id[i + 1][j], 0LL, true, 0); }

	const int goal_id = id.front().at(t);

	vll dist = g.dijkstra(goal_id);

	// debug(dist);

	vvll segs;
	auto add_seg = [&](int vertex) {
		vll v;
		rep(b, bridge_max) v.push_back(dist[id[b][vertex]]);
		segs.push_back(v);
		return;
	};

	add_seg(s1);
	add_seg(s2);

	auto find_min = [](const vll &segs, const ll &x) {
		// const int len = segs.size();
		// int large = len;
		// int small = 0;
		// auto calc = [&](int steep) { return x * steep + segs[steep]; };
		// while(large - small > 5) {
		// 	int mid = large + small;
		// 	mid /= 2;
		// 	// ll lef = x * mid + segs[mid];
		// 	// ll rig = x * (mid + 1) + segs[mid + 1];O
		// 	ll lef = calc(mid);
		// 	ll rig = calc(mid + 1);
		// 	if(lef < rig)
		// 		large = mid + 1;
		// 	else
		// 		small = mid;
		// }
		// ll ret = INF;
		// rep(i, small, large) { chmin(ret, calc(i)); }
		// return ret;

		const int len = segs.size();
		ll ret = INF;
		rep(i, len) chmin(ret, segs[i] + ll(i) * x);
		return ret;
	};

	auto calc_diffrence = [&](ll x) {
		ll ret = abs(find_min(segs[0], x) - find_min(segs[1], x));
		if(x) debug(x, ret);
		return ret;
	};

	ll ans = INF;
	chmin(ans, calc_diffrence(0LL));

	debug(segs);
	foa(seg, segs) {
		rep(i, bridge_max) rep(j, i + 1, bridge_max) {
			ll diff_const = abs(seg[i] - seg[j]);
			ll steep_dist = abs(i - j);
			if(seg[i] == g.INF || seg[j] == g.INF) continue;
			chmin(ans, calc_diffrence(diff_const / steep_dist));
			chmin(ans, calc_diffrence(dup(diff_const, steep_dist)));
		}
	}

	rep(i, bridge_max) rep(j, bridge_max) {
		// if(i == j) continue;
		ll diff_const = (segs[0][i] - segs[1][j]);
		ll stpdiff = (i - j);
		if(stpdiff) {
			// if(diff_const * stpdiff < 0) {
			diff_const = abs(diff_const);
			stpdiff = abs(stpdiff);
			chmin(ans, calc_diffrence(dup(diff_const, stpdiff)));
			chmin(ans, calc_diffrence(diff_const / stpdiff));
			// }
		}
	}

	return ans;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n;
	while(cin >> n && n) {
		cout << solve(n) << dl;
	}

	return 0;
}
accuracy: 1
time_ms: 1030
memory_kb: 23568
final_rank: 20

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define eps 1e-9
#define INF 2000000000              // 2e9
#define LLINF 2000000000000000000ll // 2e18 (llmax:9e18)
#define all(x) (x).begin(), (x).end()
#define sq(x) ((x) * (x))

#define rep(i, x) for (int i = 0; i < (int)(x); i++)
#define drep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)

#define popcount __builtin_popcount
#define next __next
#define prev __prev

#ifndef LOCAL
#define dmp(...) ;
#else
#define dmp(...)                                                               \
  cerr << "[ " << #__VA_ARGS__ << " ] : " << dump_str(__VA_ARGS__) << endl
#endif

// ---------------- Utility ------------------

template <class T>
bool chmin(T &a, const T &b) {
  if (a <= b) return false;
  a = b;
  return true;
}

template <class T>
bool chmax(T &a, const T &b) {
  if (a >= b) return false;
  a = b;
  return true;
}

template <class T>
using MaxHeap = priority_queue<T>;

template <class T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;

template <class T>
vector<T> vect(int len, T elem) {
  return vector<T>(len, elem);
}

// ----------------- Input -------------------

template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}

template <class T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) is >> vec[i];
  return is;
}

// ----------------- Output ------------------

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ',' << p.second;
}

template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (const T &e : v) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const deque<T> &d) {
  for (const T &e : d) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const set<T> &s) {
  os << "{ ";
  for (const T &e : s) os << e << " ";
  return os << "}";
}

template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &m) {
  os << "{ ";
  for (const auto &[key, val] : m) os << "( " << key << " -> " << val << " ) ";
  return os << "}";
}

template <class TupleTy, size_t... I>
void dump_tuple(ostream &os, const TupleTy t, std::index_sequence<I...>) {
  (..., (os << (I == 0 ? "" : ",") << std::get<I>(t)));
}

template <class... Args>
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
  os << "(";
  dump_tuple(os, t, std::make_index_sequence<sizeof...(Args)>());
  return os << ")";
}

void dump_str_rec(ostringstream &) {}

template <class Head, class... Tail>
void dump_str_rec(ostringstream &oss, Head &&head, Tail &&... tail) {
  oss << ", " << head;
  dump_str_rec(oss, forward<Tail>(tail)...);
}

template <class T, class... U>
string dump_str(T &&arg, U &&... args) {
  ostringstream oss;
  oss << arg;
  dump_str_rec(oss, forward<U>(args)...);
  return oss.str();
}

// --------------- Fast I/O ------------------

void fastio() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << fixed << setprecision(20);
}

// ------------------ ACL --------------------

// #include <atcoder/modint>
// constexpr int MOD = 998244353;
// constexpr int MOD = 1000000007;
// using mint = atcoder::static_modint<MOD>;
// ostream &operator<<(ostream &os, const mint &v) {
//   return os << v.val();
// }

// ------------ End of template --------------

template <class Cost = int>
struct edge {
  int from, to;
  Cost cost;
  edge() {}
  edge(int from, int to, Cost cost) : from(from), to(to), cost(cost) {}

  // for debug
  friend ostream &operator<<(ostream &os, const edge &e) {
    os << e.from << " -> " << e.to << " : " << e.cost << ", ";
    return os;
  }
};

template <class Cost = int>
struct Graph {
  int V;
  vector<vector<edge<Cost>>> G;
  Graph() {}
  Graph(int V) : V(V) { G.resize(V); }
  void add_edge(int a, int b, Cost cost = Cost(0)) {
    G[a].push_back(edge<Cost>(a, b, cost));
  }
  void add_edge_undirected(int a, int b, Cost cost = Cost(0)) {
    G[a].push_back(edge<Cost>(a, b, cost));
    G[b].push_back(edge<Cost>(b, a, cost));
  }
  size_t size() const { return G.size(); }
  const vector<edge<Cost>> &operator[](int id) const { return G[id]; }

  // for debug
  friend ostream &operator<<(ostream &os, const Graph g) {
    for (int i = 0; i < g.size(); i++) {
      os << g[i];
      if (i + 1 < g.size()) os << endl;
    }
    return os;
  }
};

// verified
// https://atcoder.jp/contests/dwacon6th-final-open/submissions/10023433
template <class Cost>
vector<Cost> dijkstra(Graph<Cost> &g, int s) {
  assert(0 <= s && s < g.size());
  vector<Cost> dist;
  dist.assign(g.size(), numeric_limits<Cost>::max());
  dist[s] = Cost(0);
  MinHeap<pair<Cost, int>> q;
  q.push(make_pair(Cost(0), s));
  while (!q.empty()) {
    auto a = q.top();
    q.pop();
    int v = a.second;
    if (dist[v] < a.first) continue;
    for (auto e : g[v]) {
      if (dist[e.to] > dist[v] + e.cost) {
        dist[e.to] = dist[v] + e.cost;
        q.push(make_pair(dist[e.to], e.to));
      }
    }
  }
  return dist;
}

#define endl "\n"
using ll = long long;
using pii = pair<int, int>;

const bool multitest = false;

bool solve() {
  int N, M, S1, S2, T;
  cin >> N >> M >> S1 >> S2 >> T;
  if (N == 0 && M == 0 && S1 == 0 && S2 == 0 && T == 0) return false;
  S1--, S2--, T--;

  vector<int> a(M), b(M);
  vector<ll> w(M);
  int K = 0;
  for (int i = 0; i < M; i++) {
    string W;
    cin >> a[i] >> b[i] >> W;
    a[i]--, b[i]--;
    if (W == "x") {
      w[i] = -1ll;
      K++;
    } else {
      w[i] = std::stoll(W);
    }
  }

  auto encode = [&](int v, int num_magical) { return v + num_magical * N; };

  Graph<ll> g((K + 1) * N);
  for (int i = 0; i < M; i++) {
    if (w[i] == -1ll) {
      for (int j = 0; j < K; j++) {
        {
          int u = encode(a[i], j), v = encode(b[i], j + 1);
          g.add_edge(u, v, 0ll);
        }
        {
          int u = encode(b[i], j), v = encode(a[i], j + 1);
          g.add_edge(u, v, 0ll);
        }
      }
    } else {
      for (int j = 0; j <= K; j++) {
        int u = encode(a[i], j), v = encode(b[i], j);
        g.add_edge(u, v, w[i]);
        g.add_edge(v, u, w[i]);
      }
    }
  }

  const ll MX = std::numeric_limits<ll>::max();

  auto d1 = dijkstra(g, S1);
  auto d2 = dijkstra(g, S2);

  // for (int k = 0; k <= K; k++) {
  //   ll D1 = d1[encode(T, k)], D2 = d2[encode(T, k)];
  //   cerr << k << ' ' << (D1 == MX ? -1 : D1) << ' ' << (D2 == MX ? -1 : D2)
  //        << endl;
  // }

  vector<ll> xs;
  xs.push_back(0ll);
  xs.push_back(10000000000000ll);

  for (int i = 0; i <= K; i++) {
    for (int j = 0; j <= K; j++) {
      if (i == j) continue;
      {
        ll A = d1[encode(T, i)], B = d1[encode(T, j)];
        if (A == MX || B == MX) continue;
        // i * x + A =  j * x + B
        ll inter_x = (A - B) / (j - i);
        for (int dx = -1; dx <= 1; dx++) {
          if (inter_x + dx >= 0ll) xs.push_back(inter_x + dx);
        }
      }
      {
        ll A = d2[encode(T, i)], B = d2[encode(T, j)];
        if (A == MX || B == MX) continue;
        // i * x + A =  j * x + B
        ll inter_x = (A - B) / (j - i);
        for (int dx = -1; dx <= 1; dx++) {
          if (inter_x + dx >= 0ll) xs.push_back(inter_x + dx);
        }
      }
      {
        ll A = d1[encode(T, i)], B = d2[encode(T, j)];
        if (A == MX || B == MX) continue;
        // i * x + A =  j * x + B
        ll inter_x = (A - B) / (j - i);
        for (int dx = -1; dx <= 1; dx++) {
          if (inter_x + dx >= 0ll) xs.push_back(inter_x + dx);
        }
      }
      {
        ll A = d2[encode(T, i)], B = d1[encode(T, j)];
        if (A == MX || B == MX) continue;
        // i * x + A =  j * x + B
        ll inter_x = (A - B) / (j - i);
        for (int dx = -1; dx <= 1; dx++) {
          if (inter_x + dx >= 0ll) xs.push_back(inter_x + dx);
        }
      }
    }
  }

  sort(all(xs));
  xs.erase(unique(all(xs)), xs.end());

  ll ans = MX;

  for (auto x : xs) {
    ll D1 = MX, D2 = MX;
    for (int k = 0; k <= K; k++) {
      ll B1 = d1[encode(T, k)], B2 = d2[encode(T, k)];
      if (B1 != MX) { chmin(D1, (ll)k * x + B1); }
      if (B2 != MX) { chmin(D2, (ll)k * x + B2); }
    }
    assert(D1 != MX && D2 != MX);
    chmin(ans, abs(D1 - D2));
  }

  cout << ans << endl;

  return true;
}

int main() {
  fastio();
  if (!multitest) {
    while (solve()) {}
  } else {
    cerr << "[Warning] Multi testcase mode on" << endl;
    int t;
    cin >> t;
    while (t--) solve();
  }
  return 0;
}
accuracy: 1
time_ms: 790
memory_kb: 20184
final_rank: 17

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 5100000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/all>
//using namespace atcoder;
//const int mod = 1e9 + 7;
const int mod = 998244353;

int main(){
    while(1){
        int n,m,s1,s2,t; cin >> n >> m >> s1 >> s2 >> t;
        if(!n) break;
        s1--; s2--; t--;
        vector<vpl> G(n);
        rep(i,m){
            int a,b; cin >> a >> b; a--; b--;
            string c; cin >> c;
            int C;
            if(c == "x") C = -1;
            else C = stoi(c);
            G[a].emplace_back(b,C);
            G[b].emplace_back(a,C);
        }
        vvl d(n,vl(101,linf));
        d[t][0] = 0;
        priority_queue<tapu,vector<tapu>,greater<tapu>> pq;
        pq.emplace(0,t,0);
        while(!pq.empty()){
            ll c,u,x;
            tie(c,u,x) = pq.top(); pq.pop();
            if(d[u][x] < c) continue;
            for(auto v : G[u]){
                int nx = x + (v.second == -1);
                ll nc = c + (v.second == -1 ? 0 : v.second);
                if(nx > 100) continue;
                if(chmin(d[v.first][nx],nc)){
                    pq.emplace(nc,v.first,nx);
                }
            }
        }
        ll ans = linf;
        rep(i,101) rep(j,101){
            P r1 = {0,linf}, r2 = {0,linf};
            if(d[s1][i] == linf || d[s2][j] == linf) continue;
            rep(k,i){
                if(d[s1][k] == linf) continue;
                if(d[s1][i] >= d[s1][k]) r1.second = -1;
                chmin(r1.second, (d[s1][k]-d[s1][i])/(i-k));
            }
            rep(k,j){
                if(d[s2][k] == linf) continue;
                if(d[s2][j] >= d[s2][k]) r2.second = -1;
                chmin(r2.second, (d[s2][k]-d[s2][j])/(j-k));
            }
            REP(k,i+1,101){
                if(d[s1][k] == linf) continue;
                chmax(r1.first, (d[s1][i]-d[s1][k]+k-i-1)/(k-i));
            }
            REP(k,j+1,101){
                if(d[s2][k] == linf) continue;
                chmax(r2.first, (d[s2][j]-d[s2][k]+k-j-1)/(k-j));
            }
            if(r1.first > r2.first) swap(r1,r2);
            if(r1.second < r2.first) continue;
            P r = {r2.first, min(r1.second,r2.second)};
            if(r.first > r.second) continue;
            // debug(i,j,d[s1][i],d[s2][j],r);
            // debug(r1,r2);
            // debug(ans);
            if(i == j) chmin(ans, abs(d[s1][i] - d[s2][j]));
            else if(i > j){
                if(d[s1][i] >= d[s2][j]){
                    chmin(ans, d[s1][i]-d[s2][j] + r.first*(i-j));
                }else{
                    ll diff = d[s2][j] - d[s1][i];
                    ll q = diff / (i-j);
                    ll X = 0;
                    if(diff-q*(i-j) > (q+1)*(i-j)-diff) q++;
                    if(q < r.first) X = r.first;
                    else if(q <= r.second) X = q;
                    else X = r.second;
                    chmin(ans, abs(d[s1][i]-d[s2][j] + X*(i-j)));
                }
            }else{
                if(d[s1][i] <= d[s2][j]){
                    chmin(ans, d[s2][j]-d[s1][i] + r.first*(j-i));
                }else{
                    ll diff = d[s1][i] - d[s2][j];
                    ll q = diff / (j-i);
                    ll X = 0;
                    if(diff-q*(j-i) > (q+1)*(j-i)-diff) q++;
                    if(q < r.first) X = r.first;
                    else if(q <= r.second) X = q;
                    else X = r.second;
                    chmin(ans, abs(d[s2][j]-d[s1][i] + X*(j-i)));
                }
            }
        }
        cout << ans << "\n";
    }
}
accuracy: 1
time_ms: 1760
memory_kb: 6860
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=1005;
const ll INF=1LL<<60;
vector<pair<int,ll>> G[MAX];

ll dis[2][MAX][105];
ll lef[2][105],righ[2][105];

void dijkstra(int s1,int s2){
    
    for(int q=0;q<2;q++){
        dis[q][s1][0]=0;
        priority_queue<pair<ll,pair<int,int>>,vector<pair<ll,pair<int,int>>>,greater<pair<ll,pair<int,int>>>> PQ;
        
        PQ.push(make_pair(0,mp(s1,0)));
        while(!PQ.empty()){
            ll a=PQ.top().first;
            int b=PQ.top().se.fi,c=PQ.top().se.se;
            PQ.pop();
            if(dis[q][b][c]<a) continue;
            for(int i=0;i<G[b].size();i++){
                int d=G[b][i].first;
                ll e=G[b][i].second;
                if(e==-1){
                    if(c+1<=100&&chmin(dis[q][d][c+1],a)) PQ.push(mp(a,mp(d,c+1)));
                }else{
                    if(chmin(dis[q][d][c],a+e)) PQ.push(mp(a+e,mp(d,c)));
                }
            }
        }
        
        swap(s1,s2);
    }
    return;
}//a,dが長さ

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    while(1){
        int N,M,s1,s2,t;cin>>N>>M>>s1>>s2>>t;
        s1--;s2--;t--;
        if(N==0) break;
        
        for(int i=0;i<N;i++){
            G[i].clear();
            for(int j=0;j<105;j++) dis[0][i][j]=dis[1][i][j]=INF;
        }
        
        for(int q=0;q<2;q++){
            for(int j=0;j<105;j++){
                lef[q][j]=INF;
                righ[q][j]=-INF;
            }
        }
        
        for(int i=0;i<M;i++){
            int a,b;string s;cin>>a>>b>>s;
            a--;b--;
            if(s=="x"){
                G[a].push_back(mp(b,-1));
                G[b].push_back(mp(a,-1));
            }else{
                G[a].push_back(mp(b,stoll(s)));
                G[b].push_back(mp(a,stoll(s)));
            }
        }
        
        dijkstra(s1,s2);
        
        for(int q=0;q<2;q++){
            for(int a=0;a<=100;a++){
                if(dis[q][t][a]==INF) continue;
                lef[q][a]=-INF;
                righ[q][a]=INF;
                bool ok=true;
                for(int b=0;b<=100;b++){
                    if(a==b) continue;
                    if(dis[q][t][b]==INF) continue;
                    ll d1=dis[q][t][a],d2=dis[q][t][b];
                    if(a>b){
                        if(d2>=d1) chmin(righ[q][a],(d2-d1)/(a-b));
                        else ok=false;
                    }else{
                        chmax(lef[q][a],(d1-d2+b-a-1)/(b-a));
                    }
                }
                if(!ok){
                    lef[q][a]=INF;
                    righ[q][a]=-INF;
                }
                //cout<<q<<" "<<a<<" "<<dis[q][t][a]<<" "<<lef[q][a]<<" "<<righ[q][a]<<endl;
            }
        }
        
        ll ans=INF;
        
        for(int a=0;a<=100;a++){
            for(int b=0;b<=100;b++){
                ll l=max(lef[0][a],lef[1][b]),r=min(righ[0][a],righ[1][b]);
                chmax(l,0LL);
                if(l>r) continue;
                ll d1=dis[0][t][a],d2=dis[1][t][b];
                if(a==b) chmin(ans,abs(d1-d2));
                else{
                    for(int t=-3;t<=3;t++){
                        ll xx=(d2-d1)/(a-b)+t;
                        if(l<=xx&&xx<=r&&xx>=0) chmin(ans,abs(xx*(a-b)+d1-d2));
                        //cout<<xx<<" "<<a<<" "<<b<<endl;
                    }
                    chmin(ans,abs(l*(a-b)+d1-d2));
                    chmin(ans,abs(r*(a-b)+d1-d2));
                }
            }
        }
        
        cout<<ans<<"\n";
    }
}
accuracy: 1
time_ms: 380
memory_kb: 6992
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long long INF = 1000000000000000;
int main(){
  while (true){
    int N, M, S1, S2, T;
    cin >> N >> M >> S1 >> S2 >> T;
    if (N == 0 && M == 0 && S1 == 0 && S2 == 0 && T == 0){
      break;
    }
    S1--;
    S2--;
    T--;
    vector<vector<pair<int, int>>> E1(N);
    vector<vector<int>> E2(N);
    int cnt = 0;
    for (int i = 0; i < M; i++){
      int a, b;
      string w;
      cin >> a >> b >> w;
      a--;
      b--;
      if (w != "x"){
        E1[a].push_back(make_pair(stoi(w), b));
        E1[b].push_back(make_pair(stoi(w), a));
      } else {
        E2[a].push_back(b);
        E2[b].push_back(a);
        cnt++;
      }
    }
    vector<vector<long long>> d(N, vector<long long>(cnt + 1, INF));
    priority_queue<tuple<long long, int, int>, vector<tuple<long long, int, int>>, greater<tuple<long long, int, int>>> pq;
    pq.push(make_tuple(0, T, 0));
    while (!pq.empty()){
      long long dd = get<0>(pq.top());
      int v = get<1>(pq.top());
      int c = get<2>(pq.top());
      pq.pop();
      if (d[v][c] == INF){
        d[v][c] = dd;
        for (auto P : E1[v]){
          int w = P.second;
          if (d[w][c] == INF){
            pq.push(make_tuple(dd + P.first, w, c));
          }
        }
        if (c < cnt){
          for (int w : E2[v]){
            if (d[w][c + 1] == INF){
              pq.push(make_tuple(dd, w, c + 1));
            }
          }
        }
      }
    }
    vector<long long> L1(cnt + 1, 0), R1(cnt + 1, INF);
    for (int i = 0; i <= cnt; i++){
      for (int j = 0; j < i; j++){
        if (d[S1][j] < d[S1][i]){
          R1[i] = -1;
        } else {
          long long x = (d[S1][j] - d[S1][i]) / (i - j);
          R1[i] = min(R1[i], x);
          L1[j] = max(L1[j], x + 1);
        }
      }
    }
    vector<long long> L2(cnt + 1, 0), R2(cnt + 1, INF);
    for (int i = 0; i <= cnt; i++){
      for (int j = 0; j < i; j++){
        if (d[S2][j] < d[S2][i]){
          R2[i] = -1;
        } else {
          long long x = (d[S2][j] - d[S2][i]) / (i - j);
          R2[i] = min(R2[i], x);
          L2[j] = max(L2[j], x + 1);
        }
      }
    }
    long long ans = INF;
    for (int i = 0; i <= cnt; i++){
      for (int j = 0; j <= cnt; j++){
        if (d[S1][i] != INF && d[S2][j] != INF){
          long long L = max(L1[i], L2[j]);
          long long R = min(R1[i], R2[j]);
          if (L <= R){
            long long A = (L * i + d[S1][i]) - (L * j + d[S2][j]);
            long long B = (R * i + d[S1][i]) - (R * j + d[S2][j]);
            if (i == j){
              ans = min(ans, abs(A));
            } else if (A >= 0 && B >= 0){
              ans = min(ans, min(A, B));
            } else if (A <= 0 && B <= 0){
              ans = min(ans, min(-A, -B));
            } else {
              long long r = max(A, B) % abs(i - j);
              ans = min(ans, r);
              ans = min(ans, abs(i - j) - r);
            }
          }
        }
      }
    }
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 250
memory_kb: 7172
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long long INF = 1000000000000000;
int main(){
  while (true){
    int N, M, S1, S2, T;
    cin >> N >> M >> S1 >> S2 >> T;
    if (N == 0 && M == 0 && S1 == 0 && S2 == 0 && T == 0){
      break;
    }
    S1--;
    S2--;
    T--;
    vector<vector<pair<int, int>>> E1(N);
    vector<vector<int>> E2(N);
    int cnt = 0;
    for (int i = 0; i < M; i++){
      int a, b;
      string w;
      cin >> a >> b >> w;
      a--;
      b--;
      if (w != "x"){
        E1[a].push_back(make_pair(stoi(w), b));
        E1[b].push_back(make_pair(stoi(w), a));
      } else {
        E2[a].push_back(b);
        E2[b].push_back(a);
        cnt++;
      }
    }
    vector<vector<long long>> d(N, vector<long long>(cnt + 1, INF));
    priority_queue<tuple<long long, int, int>, vector<tuple<long long, int, int>>, greater<tuple<long long, int, int>>> pq;
    pq.push(make_tuple(0, T, 0));
    while (!pq.empty()){
      long long dd = get<0>(pq.top());
      int v = get<1>(pq.top());
      int c = get<2>(pq.top());
      pq.pop();
      if (d[v][c] == INF){
        d[v][c] = dd;
        for (auto P : E1[v]){
          int w = P.second;
          if (d[w][c] == INF){
            pq.push(make_tuple(dd + P.first, w, c));
          }
        }
        if (c < cnt){
          for (int w : E2[v]){
            if (d[w][c + 1] == INF){
              pq.push(make_tuple(dd, w, c + 1));
            }
          }
        }
      }
    }
    vector<long long> L1(cnt + 1, 0), R1(cnt + 1, INF);
    for (int i = 0; i <= cnt; i++){
      for (int j = 0; j < i; j++){
        if (d[S1][j] < d[S1][i]){
          R1[i] = -1;
        } else {
          long long x = (d[S1][j] - d[S1][i]) / (i - j);
          R1[i] = min(R1[i], x);
          if ((d[S1][j] - d[S1][i]) % (i - j) == 0){
            L1[j] = max(L1[j], x);
          } else {
            L1[j] = max(L1[j], x + 1);
          }
        }
      }
    }
    vector<long long> L2(cnt + 1, 0), R2(cnt + 1, INF);
    for (int i = 0; i <= cnt; i++){
      for (int j = 0; j < i; j++){
        if (d[S2][j] < d[S2][i]){
          R2[i] = -1;
        } else {
          long long x = (d[S2][j] - d[S2][i]) / (i - j);
          R2[i] = min(R2[i], x);
          if ((d[S2][j] - d[S2][i]) % (i - j) == 0){
            L2[j] = max(L2[j], x);
          } else {
            L2[j] = max(L2[j], x + 1);
          }
        }
      }
    }
    long long ans = INF;
    for (int i = 0; i <= cnt; i++){
      for (int j = 0; j <= cnt; j++){
        if (d[S1][i] == INF || d[S2][j] == INF){
          continue;
        }
        long long L = max(L1[i], L2[j]);
        long long R = min(R1[i], R2[j]);
        if (L <= R){
          long long A = (L * i + d[S1][i]) - (L * j + d[S2][j]);
          long long B = (R * i + d[S1][i]) - (R * j + d[S2][j]);
          if (i == j){
            ans = min(ans, abs(A));
          } else if (A >= 0 && B >= 0){
            ans = min(ans, min(A, B));
          } else if (A <= 0 && B <= 0){
            ans = min(ans, min(-A, -B));
          } else {
            long long r = max(A, B) % abs(i - j);
            ans = min(ans, r);
            ans = min(ans, abs(i - j) - r);
          }
        }
      }
    }
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 270
memory_kb: 7152
final_rank: 6

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <utility>
using namespace std;
typedef long long int lli;
const lli inf = 1e18;

void update_border(vector<lli> &dp, vector<lli> &lb, vector<lli> &ub){
    for(int i=0; i<101; i++){
        if(dp[i] == inf){
            lb[i] = inf;
            ub[i] = 0;
            continue;        
        }
        for(int j=0; j<101; j++){
            if(i == j) continue;
            if(dp[j] == inf) continue;
            if(i > j){
                ub[i] = min(ub[i], (dp[j]-dp[i])/(i-j));
            }else{
                lb[i] = max(lb[i], (dp[i]-dp[j]+j-i-1)/(j-i));
            }
        }
    }
}
struct state{
    int v,e;
    lli d;
    state(int v, int e, lli d):v(v),e(e),d(d){}
    state();
    bool operator <(const state &a) const{
        return d > a.d;
    }
};
lli solve(int s1, int s2, int t, vector<vector<pair<int,lli>>> &g){
    int n = g.size();
    vector<vector<lli>> dp(n, vector<lli>(101, inf));
    dp[t][0] = 0;
    priority_queue<state> wait;
    wait.push(state(t, 0, 0));
    while(!wait.empty()){
        int v = wait.top().v;
        int e = wait.top().e;
        lli d = wait.top().d;
        wait.pop();
        if(d > dp[v][e]) continue;
        for(auto next: g[v]){
            int nv = next.first;
            int ne = (next.second == -1)? e+1: e;
            lli nd = (next.second == -1)? d: d+next.second;
            if(ne >= 101) continue;
            if(nd < dp[nv][ne]){
                dp[nv][ne] = nd;
                wait.push(state(nv, ne, nd));
            }
        }
    }

    vector<lli> lb1(101, 0), lb2(101, 0);
    vector<lli> ub1(101, inf), ub2(101, inf);
    update_border(dp[s1], lb1, ub1);
    update_border(dp[s2], lb2, ub2);

    lli ans = inf;
    for(int i=0; i<101; i++){
        for(int j=0; j<101; j++){
            if(dp[s1][i] == inf) continue;
            if(dp[s2][j] == inf) continue;
            lli lb = max(lb1[i], lb2[j]);
            lli ub = min(ub1[i], ub2[j]);
            if(lb > ub) continue;
            if(i == j){
                ans = min(ans, abs(dp[s1][i] -dp[s2][j]));
                continue;
            }
            lli ideal = (dp[s2][j]-dp[s1][i])/(i-j);
            for(int d=0; d<2; d++){
                if(lb <= ideal and ideal <= ub){
                    ans = min(ans, abs((dp[s1][i]+ideal*i)-(dp[s2][j]+ideal*j)));
                }
                ideal++;
            }
            ans = min(ans, abs((dp[s1][i]+lb*i)-(dp[s2][j]+lb*j)));
            ans = min(ans, abs((dp[s1][i]+ub*i)-(dp[s2][j]+ub*j)));
        }
    }
    return ans;
}

int main(){
    while(1){
        int n,m,s1,s2,t;
        cin >> n >> m >> s1 >> s2 >> t;
        s1--; s2--; t--;
        if(n == 0) break;

        vector<vector<pair<int,lli>>> adj(n);
        for(int i=0; i<m; i++){
            int a,b;
            string s;
            cin >> a >> b >> s;
            a--; b--;
            lli c;
            if(s == "x") c = -1;
            else c = stoll(s);
            adj[a].emplace_back(b, c);
            adj[b].emplace_back(a, c);
        }
        cout << solve(s1, s2, t, adj) << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 5712
final_rank: 1