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

#define ll long long
#define ii pair <int,int>
#define F first
#define S second
#define ever (;;)

const int N = 100100;

int n,m,x,y,par[N];
ll dis[N],inf=1e18;
vector < pair <int,ii> > adj[N];
priority_queue < pair < ll , int > , vector < pair < ll , int > > , greater < pair < ll , int > > > q;

int get(int x) { return par[x] == x ? x : par[x] = get(par[x]); }

void mrg(int x,int y)
{
    x = get(x);
    y = get(y);

    if( x == y )
        return;

    par[x] = y;
}

void dijkstra(int p)
{
    for(int i=1;i<=n;i++)
        dis[i] = inf;

    dis[p] = 0;
    q.push( { 0 , p } );

    while( !q.empty() )
    {
       // ll w = q.top().F;
        int u = q.top().S;
          ll w = dis [u];
        q.pop();

        //if( dis[u] < w )
            //continue;

        for(auto &X:adj[u])
        {
            int x = X.F;
            int t = X.S.F;
            int k = X.S.S;

            int toreach = (k-w%k)%k;
            if( dis[x] > dis[u] + toreach + t )
            {
                dis[x] = dis[u] + toreach + t;
                q.push( { dis[x] , x } );
            }
        }
    }
}

int main()
{
    scanf("%d%d%d%d",&n,&m,&x,&y);
    for(int i=1;i<=n;i++)
        par[i] = i;
    for(int i=1;i<=m;i++)
    {
        int a,b,t,k;
        scanf("%d%d%d%d",&a,&b,&t,&k);
        adj[a].push_back( { b , { t , k } } );
        adj[b].push_back( { a , { t , k } } );
        mrg(a,b);
    }

    if( get(x) != get(y) )
    {
        printf("-1\n");
        return 0;
    }

    dijkstra(x);

    printf("%lld\n",dis[y]);
}

#include "bits/stdc++.h"
/*
#include <ext/pb_ds/assoc_container.hpp> // Common file 
#include <ext/pb_ds/tree_policy.hpp> 
#include <functional> // for less 
using namespace __gnu_pbds; 
// a new data structure defined. Please refer below 
// GNU link : https://goo.gl/WVDL6g 
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> new_data_set; 
//new_data_set p; 
//p.find_by_order(3)
//p.order_of_key(6)
*/
//#include <algorithm>
#define ll long long 
#define mod 1000000007
#define mk make_pair
#define pb push_back
#define fi first
#define se second
#define umap unordered_map
#define uset unordered_set
#define lb lower_bound
#define ub upper_bound
#define endll "\n";
#define all(x) (x).begin(), (x).end()
#define forr(it,x) for(auto it=x.begin();it!=x.end();it++)
#define for1(i,a,b) for(int i=a;i<b;i++)
#define for2(i,a,b) for(int i=a;i>=b;i--)
#define for3(i,a,b) for(long long int i=a;i<b;i++)
#define for4(i,a,b) for(long long int i=a;i>=b;i--)
#define pp pair<int,int>
#define ld long double
#define pll pair<ll,ll>
#define vll vector<ll>
#define vpp vector<pp>
#define vi vector<int>
#define vpll vector<pll>
#define vld vector<ld>
#define vvld vector<vld>
#define vvi vector<vi>
#define vvll vector<vll>
#define vvpll vector<vpll>
#define vvpp vector<vpp>
#define I insert
#define mem(a,x) memset(a,x,sizeof(a))
#define p_queue(a) priority_queue<a,vector<a>,greater<a>>
using namespace std;
//const int dx[8]={1,0,-1,0,1,1,-1,-1},dy[8]={0,1,0,-1,-1,1,-1,1};
//const int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1}; 
const int N=2e5+5;
const int INF = 1e9+5;
/*vector<bool> p(N+1, true);
void sieve()
{
  p[0] = p[1] = false;
  int i,j;
  for (i = 2; i*i <= N; i++) 
  {
      if (p[i]) 
      {
          for (j = i * i; j <=N; j += i)
            {
        p[j] =false;
        }
      }
  }
}*/
/*ll power(ll a1, ll b1){
    ll res = 1;
    while(b1 > 0){
        if(b1 % 2){
            res = 1LL * res * a1 % mod;
        }
        a1 = 1LL * a1 * a1 % mod;
        b1 /= 2;
    }
    return res;
}
ll invmod(ll a1,ll b1){
  return power(a1,b1-2);
}*/
/*ll ncr(int n1,int c1){
  if(n1<c1)
    return 0;
  if(n1==c1||c1==0)
    return 1;
  ll n=n1,c=c1;
  vll fact(n+1,1);
  for1(i,1,n+1){
    fact[i]=fact[i-1];
    fact[i]*=i;
    fact[i]%=mod;
  }
  ll fact1=fact[n];
  ll fact2=fact[c];
  ll fact3=fact[n-c];
  fact1*=invmod(fact2,mod);fact1%=mod;
  fact1*=invmod(fact3,mod);fact1%=mod;
  return fact1;
}*/
/*int gcd(int a,int b){
    if(a<b) swap(a,b);
    if(b==0) return a;
    a%=b;
    return gcd(b,a);
}*/
/*int lcm(int a,int b){
   return (a*1LL*b)/gcd(a,b);
}*/
vll dist,vis;
vector<vector<int>> adj[N];
int main()
{
    ios_base::sync_with_stdio(false);cin.tie(NULL);
    int n,m,x,y,u,v,t1,k1;cin>>n>>m>>x>>y;
    dist.resize(n+1,1e18);vis.resize(n+1,0);
    for1(i,0,m){
      cin>>u>>v>>t1>>k1;
      adj[u].pb({v,k1,t1});
      adj[v].pb({u,k1,t1});
    }
    dist[x]=0;
    p_queue(pll) pq;
    for1(i,1,n+1){
      pq.push({dist[i],i});
    }
    while(!pq.empty()){
      pair<ll,int> src=pq.top();pq.pop();
      //cout<<src.se<<endll;
      if(!vis[src.se]){
        vis[src.se]=1;
        for(auto x:adj[src.se]){
          if(!vis[x[0]]){
            /*ll t2=(src.fi+x[2]+x[1]-1)/(x[1]);
            t2*=x[1];
            if(dist[x[0]]>src.fi+x[1]){
              dist[x[0]]=src.fi+x[1];pq.push({t2,x[0]});
            }
            //cout<<x[0]<<" "<<dist[x[0]]<<" "<<t2<<endll;*/
            ll t2=(src.fi+x[1]-1)/x[1];
            t2*=x[1];t2+=x[2];
            if(dist[x[0]]>t2){
              dist[x[0]]=t2;pq.push({t2,x[0]});
            }
          }
        }
      }
    }
    //for1(i,1,n+1) cout<<dist[i]<<" ";
    //cout<<endll;
    if(dist[y]==1e18){
      cout<<-1<<endll;
    }
    else{
      cout<<dist[y]<<endll;
    }
    return 0;
}

/*

*/


