 /*Jai Shree Ram*/
// Never Give Up
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
 
#define ff              first
#define ss              second
#define int             long long
#define pb              push_back
#define mp              make_pair
#define pii             pair<int,int>
#define vi              vector<int>
#define mii             map<int,int>
#define umii            unordered_map<int,int>
#define pqb             priority_queue<int>
#define pqs             priority_queue<int,vi,greater<int> >
#define setbits(x)      __builtin_popcountll(x)
#define zrobits(x)      __builtin_ctzll(x)
#define mod             1000000007
#define inf             1e18
#define ps(x,y)         fixed<<setprecision(y)<<x
#define mk(arr,n,type)  type *arr=new type[n];
#define w(x)            int x; cin>>x; while(x--)
#define F(i,s,e,j)        for(int i=s;i<=e;i+=j)
#define mt19937                 rng(chrono::steady_clock::now().tjhe_since_epoch().count());   
//shuffle(arr,arr+n,rng)
 void c_p_c()
{
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}
vector<vi> graph[100001];
int32_t main()
{   c_p_c();
    int n,m,x,y;
    cin>>n>>m>>x>>y;
    vi vt(3);
    for(int i=0;i<m;i++)
    {
        int a,b,t,k;
        cin>>a>>b>>vt[1]>>vt[2];
        vt[0] = b;
        graph[a].pb(vt);
        vt[0] = a;
        graph[b].pb(vt);
    }
   priority_queue<pii,vector<pii>,greater<pii> > pq;
   pq.push(mp(0,x));
   vector<bool> vis(n+1,false);
   int ans = -1;
   while(!pq.empty())
   {
     pii node = pq.top();
     pq.pop();
     if(vis[node.ss])
        continue;
     vis[node.ss] = true;
     if(node.ss==y)
     {
        ans = node.ff;
        break;
     }

     for(vi v:graph[node.ss])
     {
        if(!vis[v[0]])
        {
            int t = node.ff;
            t += node.ff%v[2]==0?0:v[2]-node.ff%v[2];
            t += v[1];
            pq.push(mp(t,v[0]));
        }
     }
   }
   cout<<ans<<endl;
} 
#include <bits/stdc++.h>
using namespace std;
#define forn(i, n) for(int i = 0; i < int(n); i++)
#define fore(i, l, r) for(int i = int(l); i < int(r); i++)
#define pb push_back
#define all(x) x.begin(), x.end()
#define sz(a) int((a).size())
typedef long long ll;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<ll> vl;
typedef vector<vector<ll>> vvl;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod = 1e9 + 7;
template<class T, class U> inline void add_self(T &a, U b){a += b;if (a >= mod) a -= mod;if (a < 0) a += mod;}
template<class T, class U> inline void min_self(T &x, U y) { if (y < x) x = y; }
template<class T, class U> inline void max_self(T &x, U y) { if (y > x) x = y; }

#define _deb(x) cout<<x;
void _print() {cerr << "]\n";} template <typename T, typename... V>void _print(T t, V... v) {_deb(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#define deb(x...) cerr << "[" << #x << "] = ["; _print(x)
template <class T, class U> void print_m(const map<T,U> &m, int w=3){if(m.empty()){cout<<"Empty"<<endl; return;}for(auto x: m)cout<<"("<<x.first<<": "<<x.second<<"),"<<endl;cout<<endl;}
template<class T, class U>void debp(const pair<T, U> &pr, bool end_line=1){cout<<"{"<<pr.first<<" "<<pr.second<<"}"; cout<<(end_line ? "\n" : ", ");}
template <class T> void print_vp(const T &vp, int sep_line=0){if(vp.empty()){cout<<"Empty"<<endl; return;}if(!sep_line) cout<<"{ ";for(auto x: vp) debp(x,sep_line);if(!sep_line) cout<<"}\n";cout<<endl;}
template <typename T>void print(const T &v, bool show_index = false){int w = 2;if(show_index){for(int i=0; i<sz(v); i++)cout<<setw(w)<<i<<" ";cout<<endl;}for(auto &el: v) cout<<setw(w)<<el<<" ";cout<<endl;}
template <typename T>void print_vv(const T &vv){if(sz(vv)==0) {cout<<"Empty"<<endl; return;} int w = 3;cout<<setw(w)<<" ";for(int j=0; j<sz(*vv.begin()); j++)cout<<setw(w)<<j<<" ";cout<<endl;int i = 0;for(auto &v: vv){cout<<i++<<" {";for(auto &el: v) cout<<setw(w)<<el<<" ";cout<<"},\n";}cout<<endl;}
template <typename T> ostream& operator<<(ostream &os, const vector<T> &v){print(v); return os;};
template <typename T> ostream& operator<<(ostream &os, const vector<vector<T>> &vv){print_vv(vv); return os;};
template <class T, class U> ostream& operator<<(ostream &os, const map<T,U>  &m){print_m(m); return os;};
template <class T, class U> ostream& operator<<(ostream &os, const pair<T, U> &pr){debp(pr); return os;};
template <class T, class U> ostream& operator<<(ostream &os, const vector<pair<T, U>> &vp){ print_vp(vp); return os;};

typedef tuple<ll,ll,ll> tii; // ad, ti, ki
const ll inf =  1e18L;
int main(){
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    ll n, m; 
    while(cin>>n>>m){
        ll st, ed; cin>>st>>ed;
        vector<vector<tii>> adj(n+1);
        forn(i,m){
            ll x,y,t,k; cin>>x>>y>>t>>k;
            adj[x].pb({y,t,k});
            adj[y].pb({x,t,k});
        }

        vector<bool> vis(n+1);
        vl dist(n+1,inf);
        priority_queue<pll,vector<pll>, greater<pll>> pq; // {time, node}
        dist[st] = 0;
        pq.push({0,st});

        while(!pq.empty()){
            auto [d, node] = pq.top(); pq.pop();
            if(d>dist[node]) continue;
            vis[node] = 1;

            for(auto [ad, t, k]: adj[node]){
                if(vis[ad]) continue;
                ll depart = ((d+k-1)/k)*k;
                ll reach = depart + t;
                // deb(node,d,depart,reach,k);
                if(reach<dist[ad]){
                    dist[ad] = reach;
                    pq.push({reach,ad});
                }
            }
            // if(node==ed) break;
        }

        ll ans = dist[ed];
        cout<<(ans>=inf ? -1 : ans)<<"\n";
        

    }
    return 0;
}