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

#define rep(i,s,e)                  for (ll i = s; i <= e; ++i)
#define rrep(i,s,e)                 for (ll i = s; i >= e; --i)
#define pb                          push_back
#define pf                          push_front
#define fi                          first
#define se                          second
#define all(a)                      a.begin(), a.end()
typedef long long ll;
typedef pair<ll, ll> ii;
typedef vector<ii> vii;
typedef vector<ll> vi;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<char> vc;
typedef vector<ll> vll;

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

    ll n, m, x, y; cin >> n >> m >> x >> y;
    vector<array<ll,3>> neibs[n+1];
    rep (i,0,m-1) {
        ll a, b, t, k; cin >> a >> b >> t >> k;
        neibs[a].pb({b,t,k});
        neibs[b].pb({a,t,k});
    }

    //basic dijkstra

    priority_queue<ii, vii, greater<ii>> pq;
    pq.push({0,x});
    ll dist[n+1];
    memset(dist, -1, (n+1)*sizeof(ll));
    dist[x] = 0;

    while (!pq.empty()) {
        ll T = pq.top().fi, city = pq.top().se;
        pq.pop();
        if (dist[city] < T) continue;
        if (city==y) {
            cout << T << "\n";
            return 0;
        }
        for (array<ll,3> v : neibs[city]) {
            ll b = v[0], t = v[1], k = v[2];
            if (dist[b]==-1 || (T+k-1)/k*k+t < dist[b]) {
                dist[b] = (T+k-1)/k*k+t;
                pq.push({dist[b], b});
            }
        }
    }
    cout << "-1\n";
    return 0;
}


#include "bits/stdc++.h"
#include<sstream>
using namespace std;
typedef long long ll;
#define _USE_MATH_DEFINES
#include <math.h>
#define NIL = -1;
#define all(x) x.begin(),x.end()
const ll INF = 1e9;
const long long inf = 1e18;
const ll INFL = 1e18;
const ll MOD = 1e9 + 7;

int digit(ll x) {
    int digits = 0;
 
    while(x > 0){
        x /= 10;
        digits++;
    }
 
    return digits;
}
 
ll gcd(long long a,long long b) {
    if (a < b) swap(a,b);
    if (b == 0) return a;
    
    return gcd(b,a%b);
}
 
bool is_prime(long long N){
    if (N == 1) return false;
    for (long long i = 2;i * i <= N;i++){
        if (N % i == 0) return false;
    }
    return true;
}
 
ll lcm(ll a,ll b){
    return ((a * b == 0)) ? 0 : (a / gcd(a,b) * b);
}
 
double DegreeToRadian(double degree){
    return degree * M_PI / 180.0;
}
 
long long modpow(long long a, long long b, long long m){
    long long ans = 1;
    while(b > 0){
        if (b % 2 == 1){
            ans *= a;
            ans %= m;
        }
        a *= a;
        a %= m;
        b /= 2;
    }
    return ans;
}

long long comb(long long x, long long y){
    int z;
    if (y == 0) return 1;
    else {
        z = modpow(x, y/2, MOD)*modpow(x, y/2, MOD)%MOD;
        if (y % 2 == 1) z = z*x%MOD;
        return z;
    }
}


vector<pair<long long, long long>> prime_fact(long long x){
    vector<pair<long long, long long>> res;
    for(int i = 2;i*i <= x;i++){
        if (x % i == 0){
            long long cnt = 0;
            while(x % i == 0){
                cnt++;
                x /= i;
            }
            res.push_back({i, cnt});
        }
    }
    if (x != 1){
        res.push_back({x, 1});
    }
    return res;
}

int64_t mod_inv(int64_t a, int64_t m){
    int64_t b = m, u = 1, v = 0;

    while(b){
        int64_t t = a/b;
        a -= t*b;
        swap(a, b);
        u -= t*v;
        swap(u, v);
    }
    u %= m;
    if (u < 0) u += m;

    return u;
}


// {g, x, y}: ax + by = g
tuple<long long, long long, long long> extgcd(long long a, long long b){
    if (b == 0) return {a, 1, 0};
    long long g, x, y;
    tie(g, x, y) = extgcd(b, a % b);
    return {g, y, x - a/b*y};
}

int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};

 
//////////////////////////////////////////////////////////////

int main(){
    int n,m;
    long long x, y;
    cin >> n >> m >> x >> y;
    x--;
    y--;
    vector<vector<tuple<int, long long, long long>>> g(n + 1);
    for(int i = 0;i < m;i++){
        int a, b;
        long long t, k;
        cin >> a >> b >> t >> k;
        a--;
        b--;
        g[a].push_back(make_tuple(b, t, k));
        g[b].push_back(make_tuple(a, t, k));
    }

    vector<long long> dist(n + 1, 1e18);
    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> q;
    dist[x] = 0;
    q.push({0, x});
    long long ans = 1e18;
    while(!q.empty()){
        auto p = q.top();
        q.pop();
        for(auto nx : g[p.second]){
            if (dist[get<0>(nx)] > get<2>(nx)*((p.first + get<2>(nx) - 1) / get<2>(nx)) + get<1>(nx)){
                dist[get<0>(nx)] = get<2>(nx)*((p.first + get<2>(nx) - 1) / get<2>(nx)) + get<1>(nx);
                if(p.second == y){
                    ans = min(ans, dist[get<0>(nx)]);
                } else {
                    q.push({dist[get<0>(nx)], get<0>(nx)});
                }
            }
        }
    }

    if (dist[y] == 1e18){
        cout << -1 << endl;
    } else {
        cout << dist[y] << endl;
    }
}