#include <bits/stdc++.h>
 
using namespace std;
#define all(x) (x).begin(),(x).end()
#define rep(i, n) for (int i = 0; i < (n); i++)
#define endl "\n"
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {os << "["; for (const auto &v : vec) {os << v << ","; } os << "]"; return os;}
template <typename T, typename U> ostream &operator<<(ostream &os, const pair<T, U> &p) {os << "(" << p.first << ", " << p.second << ")"; return os;}

struct Edge {
    ll b, t, k;
};

ll f(ll now, ll k) {
    return ((now + (k - 1)) / k) * k;
}

void solve() {
    int N, M, X, Y;
    cin >> N >> M >> X >> Y;
    X--, Y--;
    vector<vector<Edge>> G(N);
    for (int i = 0; i < M; i++) {
        ll a, b, t, k;
        cin >> a >> b >> t >> k;
        a--, b--;
        G[a].push_back({b, t, k});
        G[b].push_back({a, t, k});
    }

    priority_queue<pll, vector<pll>, greater<pll>> Q;
    Q.push({0, X});
    ll INF = 2e18; 
    vector<ll> dist(N, INF);
    while(!Q.empty()) {
        pll p = Q.top(); Q.pop();
        ll d = p.first, v = p.second;
        if (d >= dist[v]) continue;
        dist[v] = d;

        for(int i = 0; i < G[v].size(); i++) {
            ll u = G[v][i].b;
            ll t = G[v][i].t;
            ll k = G[v][i].k;
            ll nt = t + ((d + (k - 1)) / k) * k;
            if (nt < dist[u]) {
                Q.push({nt, u});
            }
        }
    }
    if (dist[Y] == INF) {
        cout << -1 << endl;
    } else {
        cout << dist[Y] << endl;
    }
}

int main() {
    #ifdef LOCAL_ENV
    cin.exceptions(ios::failbit);
    #endif
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout.setf(ios::fixed);
    cout.precision(16);
    
    solve();
}
#include <bits/stdc++.h>
using namespace std;
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
// #define ordered_set tree<int, null_type,less_equal<int>, rb_tree_tag,tree_order_statistics_node_update>
#define int long long int
#define endl "\n"
#define MOD 1000000007
#define mod 1000000007
#define M 1000000007
#define pb push_back
#define take(a,b,c) for(int b=0;b<c;b++) cin>>a[b]
#define boost ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define mx 1000005
#define fiint(a,b) memset(a,b,sizeof(a))
#define bitcount __builtin_popcount
#define fori(i,a,b) for(int i=a;i<b;i++)
#define ford(i,a,b) for(int i=a;i>=b;i--)
#define debug(x) cout<<x<<endl;
#define cases(t) int t; cin>>t; while(t--)
#define inf1 INT_MAX
#define all(a) a.begin(),a.end()
#define vec vector<int>
#define pii pair<int,int>
#define plii pair<int,int>
#define pint pair<int,int>
#define ff first
#define ss second
#define lb lower_bound
#define ub upper_bound
#define bs binary_search
#define mp make_pair
 
#define sz(x) (int)x.size()
#define PI    3.14159265359
 
 
 
int factorial[10000001]={0};
 
int gcd(int a, int b){
    if (b == 0)
        return a;
    return gcd(b, a % b);
}


int powerFunction(int x,int y){
    int res = 1;
     int p = mod;
    x = x;
    while (y > 0){
        if (y & 1)
            res = (res*x)%p ;
        y = y>>1;
        x = (x*x)%p ;
    }
    return res;
}

void factorialFunction(int maxLimit){
    factorial[0]=1;
    for(int i=1 ; i <= maxLimit ; i++)
    factorial[i]=(factorial[i-1]*i)%MOD;
    return;
}
 
int nCr(int n, int r)
{
    if(r < 0 || r > n){
        return 0;
    }
    int temp = factorial[n];
    temp *= (powerFunction(factorial[r], MOD-2)%MOD);
    temp %= MOD;
    temp *= (powerFunction(factorial[n-r], MOD-2)%MOD);
    temp %= MOD;
    return temp;
}


signed main()
{
    int n,m,x,y;
    cin>>n>>m>>x>>y;
    vector<pair<int ,pii >> adj[100005];
    for(int  i = 0 ; i  < m ;i++)
    {
        int a,b,t,k;cin>>a>>b>>t>>k;
        adj[a].pb(mp(b , mp(t, k) ));
        adj[b].pb(mp(a , mp(t , k)));
    }

    vec vis(n + 1 , 0);
    priority_queue<pii , vector<pii> , greater<pii> > q;
    vec dis( n + 1, -1);
    q.push(mp( 0 ,x  ));
    dis[x] = 0;
    while(sz(q) != 0 )
    {
        int s = q.top().ss;
//int d = q.front().ff;
        q.pop();
        if(s == y)
            break;
        vis[s] = 1;
        for(auto it : adj[s])
        {
                if(vis[it.ff] == 1)
                    continue;
            int re = ( ( dis[s] % it.ss.ss == 0) ? 0 : it.ss.ss  - (dis[s] % it.ss.ss)       );
            re += dis[s] + it.ss.ff;
            if(dis[it.ff] == -1 || dis[it.ff] > re)
            {
                dis[it.ff] = re;
                q.push(mp(re , it.ff));
            }
        }
    }
    cout<<dis[y]<<endl;
}
    


