#include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for(ll i=0;i<n;i++)
#define repl(i,l,r) for(ll i=(l);i<(r);i++)
#define per(i,n) for(ll i=n-1;i>=0;i--)
#define perl(i,r,l) for(ll i=r-1;i>=l;i--)
#define fi first
#define se second
#define pb push_back
#define mkp make_pair
#define ins insert
#define pqueue(x) priority_queue<x,vector<x>,greater<x>>
#define all(x) (x).begin(),(x).end()
#define CST(x) cout<<fixed<<setprecision(x)
#define vtpl(x,y,z) vector<tuple<x,y,z>>
#define rev(x) reverse(x);
#define lin(x) ll x; cin>>x;
#define stin(x) string x; cin>>x;
#define yn(x)  if(x) {  cout<<"Yes"<<endl;   }    else {    cout<<"No"<<endl;   }
#define YN(x)  if(x) {  cout<<"YES"<<endl;   }    else {    cout<<"NO"<<endl;   }
#define co(x) cout<<x<<endl;
using ll=long long;
using ld=long double;
using vl=vector<ll>;
using vvl=vector<vector<ll>>;
using pl=pair<ll,ll>;
using vpl=vector<pl>;
using vvpl=vector<vpl>;
const ll mod=1000000007;
const ll MOD9=998244353;
const int inf=1e9+10;
const ll INF=4e18;
const ll dy[8]={1,0,-1,0,1,1,-1,-1};
const ll dx[8]={0,-1,0,1,1,-1,1,-1};
template <typename T> inline bool chmax(T &a, T b) {
    return ((a < b) ? (a = b, true) : (false));
}
template <typename T> inline bool chmin(T &a, T b) {
    return ((a > b) ? (a = b, true) : (false));
}
ll powmod(ll n, ll k, ll m) {
ll r=1;
 for(; k>0; k >>=1) {
   if(k&1) r=(r*n)%m;
   n=(n*n)%m;
 }
  return r;
}

ll fact(ll n) {
ll a=1;
rep(i,n) {
a=a*(n-i);
}
return a;
}

ll pow(ll a, ll b) {
ll x=1;
rep(i,b) {
x=x*a;
}
return x;
}


int main() {
lin(N); lin(M); lin(X); lin(Y);
vl A(M);
  vl B(M);
  vl T(M);
  vl K(M);
  rep(i,M) {
    ll a,b,t,k;
    cin>>a>>b>>t>>k;
    A.at(i)=a-1;
    B.at(i)=b-1;
    T.at(i)=t;
    K.at(i)=k;
  }
  X=X-1;
  Y=Y-1;
  
  
  
  vvpl G(N);
  rep(i,M) {
    G.at(A.at(i)).pb({B.at(i),i});
    G.at(B.at(i)).pb({A.at(i),i});
  }
  
  vl dist(N,INF);
  dist.at(X)=0;
  
  priority_queue<pl, vpl, greater<pl>>que;
  
  que.push({0,X});
  while(!que.empty()) {//que
    auto[d,v]=que.top();
    que.pop();
    if(dist[v]<d) continue;
    for(auto e:G[v]) {
      ld aa=(ld)d/(ld)K[e.se];
      ll aaa=ceil(aa);
      if(       chmin(dist[e.fi],  ((d + K[e.second] - 1) / K[e.second]) * K[e.second] + T[e.second])      ){
        que.push({dist[e.fi],e.fi});
      }
    }
    
    
    
    
    
    
    
    
  }//endque
  
  if(dist.at(Y)==INF) {
    co(-1);
  }
  else {
    co(dist.at(Y));
  }
}//end
    
    
  
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<set>
#include<queue>
#include<unordered_map>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef long double ld;
const ll inf=1e18,N=1e5+500;

ll gti(void)
{
	char c=getchar();
	ll ret=0,st=1;
	for (;c!='-'&&!isdigit(c);c=getchar());
	if (c=='-') st=-1,c=getchar();
	for (;isdigit(c);c=getchar()) ret=ret*10+c-'0';
	return ret*st;
}

struct edge{edge *nxt;int to,t,k;}pool[N<<1],*pt[N],*p=pool;
void addedge(int a,int b,int t,int k)
{
	*(++p)=(edge){pt[a],b,t,k},pt[a]=p;
	*(++p)=(edge){pt[b],a,t,k},pt[b]=p;
}
ll dis[N];
struct P
{
	ll dis;
	int id;
	bool operator<(const P &b)const
	{
		return dis>b.dis;
	}
};
ll dijkstra(int n,int s,int t)
{
	priority_queue<P> hp;
	fill(dis,dis+n+1,inf);
	dis[s]=0,hp.push((P){dis[s],s});
	while (hp.size())
	{
		P now=hp.top();
		hp.pop();
		if (dis[now.id]!=now.dis)
			continue;
		for (edge *i=pt[now.id];i;i=i->nxt)
		{
			ll tm=now.dis+(i->k-now.dis%i->k)%i->k+i->t;
			if (dis[i->to]>tm)
				dis[i->to]=tm,hp.push((P){dis[i->to],i->to});
		}
	}
	if (dis[t]==inf) return -1;
	return dis[t];
}
int main(void)
{
	int n=gti(),m=gti(),x=gti(),y=gti();
	for (int i=1;i<=m;i++)
	{
		int u=gti(),v=gti(),t=gti(),k=gti();
		addedge(u,v,t,k);
	}
	printf("%lld\n",dijkstra(n,x,y));
	return 0;
}
