#include<iostream>
#include<algorithm>
#include<math.h>
#include<cstring>
#include<vector>
#include<queue>
#define ll long long
const int N=2e5+10;
const ll mod=1e9+7;
ll read(){
    ll s = 0, f = 1; char ch = getchar();
    while(!isdigit(ch)){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(isdigit(ch)) s = (s << 3) + (s << 1) + (ch ^ 48), ch = getchar();
    return s * f;
}
using namespace std;
struct edge{
	int u,v;
	ll time,K;
	edge(int u,int v,ll time, ll K){
		this->u=u;
		this->v=v;
		this->time=time;
		this->K=K;
	}
};
struct node{
	int u;
	ll time;
	bool operator <(const node &a) const{
		return time>a.time;
	}
	node(int u,ll time){
		this->u=u;
		this->time=time;
	}
};
vector<edge> e[N];
bool vis[N];
ll arr[N];
ll dj(int n,int x,int y){
	//³õÊ¼»¯
	for(int i=1;i<=n;i++){
		arr[i]=-1;
		vis[i]=false;
	} 
	arr[x]=0;
	priority_queue<node> q;
	node t(x,0);
	q.push(t);
	while(!q.empty()){
		t=q.top();
		q.pop();
		int u=t.u;
		if(vis[u]) continue;
		vis[u]=true;
		for(int i=0;i<e[u].size();i++){
			int v=e[u][i].v;
			if(vis[v]) continue;
			ll ans=(arr[u]+e[u][i].K-1)/e[u][i].K*e[u][i].K+e[u][i].time;
			if(ans<arr[v]||arr[v]==-1){
				arr[v]=ans;
				q.push(node(v,ans));
			}
		}
	}
	return arr[y];
}
int main (){
    int n,m,x,y;
    n=read();
    m=read(); x=read(); y=read();
    int u,v,time,k;
    for(int i=1;i<=m;i++){
    	u=read();v=read();
    	time=read();
    	k=read();
    	e[u].push_back(edge(u,v,time,k));
    	e[v].push_back(edge(v,u,time,k));
	}
	cout<<dj(n,x,y)<<endl;
	return 0;
} 
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <set>
#include <queue>
#include <stack>
using namespace std;
typedef long long int ll;
typedef pair<int,int> Pai;

ll gcd(ll a, ll b) { return b?gcd(b,a%b):a;}
ll lcm(ll a, ll b) { return a/gcd(a,b)*b;}

void P(int x) {cout << x << endl;}
void P(long x) {cout << x << endl;}
void P(double x) {cout << x << endl;}
void P(ll x) {cout << x << endl;}
void P(string x) {cout << x << endl;}
void P(char x) {cout << x << endl;}

#define YES cout << "YES" << endl
#define Yes cout << "Yes" << endl
#define NO cout << "NO" << endl
#define No cout << "No" << endl

#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define drep(i, n) for(int i = n - 1; i >= 0; i--)

const int INF = 1001001001;
const ll LINF = 1001002003004005006ll;

struct to {
  int b;
  ll t;
  ll k;
};

struct queIn {
  int now;
  ll time;
};

int main() {
  int n, m, x, y;
  cin >> n >> m >> x >> y;
  x--; y--;
  vector< vector<struct to> > v(n);
  rep (i, m) {
    int a, b, t, k;
    cin >> a >> b >> t >> k;
    a--; b--;
    struct to tmp;
    tmp.b = b;
    tmp.t = t;
    tmp.k = k;
    v[a].push_back(tmp);
    tmp.b = a;
    v[b].push_back(tmp);
  }

  // rep (i, n) {
  //   rep (j, v[i].size()) {
  //     cout << i << " => " << "b: " << v[i][j].b << ", t: " << v[i][j].t << ", k: " << v[i][j].k << endl;
  //   }
  // }

  ll fast[n];
  rep (i, n) fast[i] = LINF;
  fast[x] = 0;
  struct queIn que;
  que.now = x;
  que.time = 0;
  // queue<struct queIn> q;
  auto compare = [](struct queIn a, struct queIn b) {
    return a.time > b.time;
  };

  priority_queue<
    struct queIn,
    vector<struct queIn>,
    decltype(compare) // 比較関数オブジェクトを指定
  > q {compare};
  q.push(que);
  while (!q.empty()) {
    que = q.top(); q.pop();
    // cout << "now: " << que.now << endl;
    rep (i, v[que.now].size()) {
      ll bai = que.time / v[que.now][i].k;
      if (que.time % v[que.now][i].k != 0) {
        bai++;
      }

      // cout << que.now << " => " << "b: " << v[que.now][i].b << ", t: " << v[que.now][i].t << ", k: " << v[que.now][i].k << endl;

      if (fast[v[que.now][i].b] > bai * v[que.now][i].k + v[que.now][i].t) {
        fast[v[que.now][i].b] = bai * v[que.now][i].k + v[que.now][i].t;
        struct queIn qTmp;
        qTmp.now = v[que.now][i].b;
        qTmp.time = bai * v[que.now][i].k + v[que.now][i].t;
        q.push(qTmp);
      }
    }
  }

  // rep (i, n) {
  //   cout << i << ": " << fast[i] << endl;
  // }

  if (fast[y] == LINF) {
    P(-1);
  } else {
    P(fast[y]);
  }



  return 0;
}