#include <bits/stdc++.h>
#define INF 1000000007
#define F first
#define S second
#define PB push_back
#define MP make_pair
#define REP(i,a,b) for (int i = a; i < b; i++)
 
using namespace std;
 
typedef long long ll;
typedef long long int  lli;
typedef long double ld;
typedef vector<int> vi;
typedef unordered_map<int,int> umi ;
typedef unordered_set<int> usi ;
typedef pair<int,int> pi;
#include <bits/stdc++.h>

using namespace std;

void __print(int x) {cerr << x;}
void __print(long x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(unsigned x) {cerr << x;}
void __print(unsigned long x) {cerr << x;}
void __print(unsigned long long x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const char *x) {cerr << '\"' << x << '\"';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}

template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ','; __print(x.second); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";}
void _print() {cerr << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifndef ONLINE_JUDGE
#define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
#define debug(x...)
#endif


 
 
//declare here -------------------------------------------------------------------------------
const int N =1e5+1 ;
struct edge{
	int D ;
	int T ;
	int K ;
} ;
vector<edge> adj[N] ;
ll dist[N] ;
bool visited[N] ;



// solve here ---------------------------------------------------------------------------------

void solve(){
	int n,m,x,y; 
	REP(i,0,N) dist[i]=LLONG_MAX ;
	cin>>n>>m>>x>>y ;
	int u,v,t,k ;
	edge e1 ;
	edge e2 ;
	REP(i,0,m){
		cin>>u>>v>>t>>k ;
		e1.T=t ; e2.T= t ; e1.K=k ; e2.K=k ;
		e1.D=v ; e2.D= u ;
		adj[u].PB(e1) ;
		adj[v].PB(e2) ;
	}

	dist[x]=0 ;
	priority_queue<pair<ll,ll>> q ;
	q.push({0,x}) ;

	while(!q.empty()){
		u=q.top().S ; q.pop() ;
		if(visited[u]) continue ;
		debug(u,dist[u]) ;
		visited[u]=true ;
		for(auto e:adj[u]){
			v=e.D ;
			ll add=e.T ;
			if(dist[u]%e.K==0) add+=0 ;
			else add += (e.K - (dist[u] % e.K)) ;
			if(dist[u]+add < dist[v]){
				dist[v]=dist[u]+add ;
				q.push({-dist[v] ,v}) ;
			}
		}
	}
	if(dist[y]==LLONG_MAX) cout<<-1 ;
	else cout<<dist[y] ;

	
}

 

//--------------------------------------------------------------------------------------------





int main(){
	#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
	#endif
    ios::sync_with_stdio(0);
    cin.tie(0);
    long long test =1 ;
   	//cin>>test ;
    while(test--){
        solve() ;
        cout<<"\n" ;
    }
    return 0 ;
}
#include <bits/stdc++.h>
#include <math.h>

using namespace std;

template<typename T>
long long modpow(const T n,const T p,const T mod);
template<typename T>
long long modinv(const T n,const T mod);
template<typename T>
bool chmax(T &a,const T &b);
template<typename T>
bool chmin(T &a,const T &b);

long long inf=1000000007;

struct train{
	long long to;
	long long time;
	long long inter;
};

int main(){
	long long n,m,x,y;
	cin>>n>>m>>x>>y;
	vector<vector<train>> kankei(n+1);

	for(long long i=0;i<m;i++){
		long long a,b,t,k;
		cin>>a>>b>>t>>k;
		train hoge={b,t,k};
		train fuga={a,t,k};

		kankei.at(a).push_back(hoge);
		kankei.at(b).push_back(fuga);
	}

	vector<long long> graph(n+1,inf*inf);
	graph.at(x)=0;
	priority_queue<pair<long long,long long>,vector<pair<long long,long long>>,greater<pair<long long,long long>>> que;
	que.push(make_pair(0,x));

	while(!que.empty()){
		long long here=que.top().second;
		long long now=que.top().first;
		que.pop();
		if(graph.at(here)!=now) continue;
		if(here==y){
			cout<<now<<endl;
			return 0;
		}

		for(auto next:kankei.at(here)){
			long long nto=next.to;
			long long ntime=next.time;
			long long ninter=next.inter;

			long long hogetime=now;
			if(now%ninter!=0) hogetime+=ninter-now%ninter;
			hogetime+=ntime;

			if(graph.at(nto)>hogetime){
				graph.at(nto)=hogetime;
				que.push(make_pair(hogetime,nto));
			}
		}
	}

	cout<<-1<<endl;

	return 0;
}

template<typename T>
long long modpow(const T n,const T p,const T mod){
	if(p==0) return 1;
	if(p%2==0){
		long long a=modpow(n,p/2,mod);
		return a*a%mod;
	}
	if(p%2==1) return (modpow(n,p-1,mod)*n)%mod;
	cerr<<"ERROR"<<endl;
	return 1;
}

template<typename T>
long long modinv(const T n,const T mod){
	return modpow(n,mod-2,mod);
}

template<typename T>
bool chmax(T &a,const T &b){
	if(a<b){
		a=b;
		return 1;
	}
	return 0;
}

template<typename T>
bool chmin(T &a,const T &b){
	if(a>b){
		a=b;
		return 1;
	}
	return 0;
}
