#include <bits/stdc++.h>          
using namespace std;
using ll = long long;
using ld = long double;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define repp(i, st, en) for (ll i = (ll)st; i < (ll)(en); i++)
#define repm(i, st, en) for (ll i = (ll)st; i >= (ll)(en); i--)
#define all(v) v.begin(), v.end()
void chmax(ll &x, ll y) {x = max(x,y);}
void chmin(ll &x, ll y) {x = min(x,y);}
void Yes() {cout << "Yes" << endl; exit(0);}
void No() {cout << "No" << endl; exit(0);}
template<class in_Cout> void Cout(in_Cout x) {cout << x << endl; exit(0);}

const ll inf = 1e18;
const ll mod = 1e9 + 7;

struct edge {
    ll to, cost, K;
};

vector<edge> G[110000];
ll dist[110000];

ll dijkstra(ll s, ll g) {
    rep(i,110000) dist[i] = inf;
    dist[s] = 0LL;
    priority_queue<pair<ll,ll>,vector<pair<ll,ll>>,greater<pair<ll,ll>>> que;
    que.push({0,s});
    while (que.size()) {
        pair<ll,ll> p = que.top();
        que.pop();
        ll now = p.second, t = p.first;
        if (dist[now]<t) continue;
        for (edge e : G[now]) {
            ll to = e.to, cost = e.cost, K = e.K;
            ll dt = (K - (t % K)) % K;
            if (dist[to] <= t + dt + cost) continue;
            dist[to] = t + dt + cost;
            que.push({dist[to],to});
        }
    }
    if (dist[g]==inf) return -1;
    else return dist[g];
}

int main() {
    ll N, M, X, Y;
    cin >> N >> M >> X >> Y;
    rep(i,M) {
        ll a, b, t, k;
        cin >> a >> b >> t >> k;
        G[a].push_back({b,t,k});
        G[b].push_back({a,t,k});
    }
    cout << dijkstra(X,Y) << endl;
}
#include <bits/stdc++.h>
using namespace std;

#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
#define rep3(i,m,n) for(int (i)=m;(i)<=(n);(i)++)
#define rep3rev(i,m,n) for(int (i)=m;(i)>=(n);(i)--)
#define all(a) (a.begin()),(a.end())
#define rall(a) (a.rbegin()),(a.rend())
#define fi first
#define se second
#define pb push_back
#define eb emplace_back

using ll = long long;
using vll = vector<ll>;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using P = pair<int, int>;
using LD = long double;

template <typename T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; }
template <typename T> bool chmin(T &a, const T &b) { if (a > b) { a = b; return true; } return false; }
template <typename T> void coutall(T v) { for(auto i = v.begin(); i != --v.end(); i++){cout << *i << " ";} cout << *--v.end() << endl; }
void yes(bool ok = true){ cout << (ok ? "yes" : "no") << endl; }
void Yes(bool ok = true){ cout << (ok ? "Yes" : "No") << endl; }
void YES(bool ok = true){ cout << (ok ? "YES" : "NO") << endl; }
ll myceil(ll a, ll b) { return (a + (b - 1)) / b; }

int n, m; 
vector<vector<P>> to;
vector<P> edge;
vi c;
vector<string> ans;

void dfs(int v){
    for(auto [u, id] : to[v]){
        if(c[v] > c[u]){
            // v -> u 
            if(edge[id].fi == v) ans[id] = "->";
            else ans[id] = "<-";
        }else if(c[v] < c[u]){
            // u -> v 
            if(edge[id].fi == v) ans[id] = "<-";
            else ans[id] = "->";
        }else{
            ans[id] = "?";
        }
    }
}

void dfs2(int v, int p = -1){
    for(auto [u, id] : to[v]){
        if(u == p) continue;
        if(ans[id] != "?") continue;
        if(edge[id].fi == v) ans[id] = "->";
        else ans[id] = "<-";
        dfs2(u, v);
    }
}

void Main(){
    cin >> n >> m;
    to.resize(n);
    c.resize(n);
    edge.resize(m);
    ans.resize(m);
    rep(i, m){
        int a, b; cin >> a >> b;
        a--; b--;
        to[a].pb({b, i});
        to[b].pb({a, i});
        edge[i] = {a, b};
    }
    rep(i, n) cin >> c[i];
    rep(i, n) dfs(i);
    rep(i, m) {
        if(ans[i] == "?") dfs2(edge[i].fi);
    }
    rep(i, m) cout << ans[i] << endl;
    return;
}

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