#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll INF=1e17;
const int N=1e5+3,M=1e5+3;
template <typename T>
inline void read(T &x){
  x=0;char ch=getchar();bool f=false;
  while(!isdigit(ch)) f|=ch=='-',ch=getchar();
  while(isdigit(ch))  x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
  x=f?-x:x;
}
template <typename T>
inline void print(T x){
  if(x<0) putchar('-'),x=-x;
  if(x>9) print(x/10);
  putchar(x%10^48);
}
int n,m,st,ed;
ll k[M<<1],t[M<<1];
int head[N],to[M<<1],Next[M<<1],tot;
ll dist[N];
priority_queue<pair<ll,int> > pq;
bool vis[N];
inline void Addedge(int u,int v,ll w1,ll w2){to[++tot]=v,Next[tot]=head[u],head[u]=tot,k[tot]=w2,t[tot]=w1;return;}
inline ll DJ(){
  for(register int i=1;i<=n;++i)  dist[i]=INF;
  dist[st]=0;
  pq.push(make_pair(0,st));
  while(!pq.empty()){
    int x=pq.top().second;pq.pop();
    if(vis[x])  continue;
    vis[x]=true;
    if(x==ed) return dist[ed];
    for(register int i=head[x];i;i=Next[i]){
      int y=to[i];
      if(dist[x]%k[i]==0){
        if(dist[y]>dist[x]+t[i]){
          dist[y]=dist[x]+t[i];
          pq.push(make_pair(-dist[y],y));
        }
      }
      else{
        ll tep=(dist[x]/k[i]+1)*k[i];
        if(dist[y]>tep+t[i]){
          dist[y]=tep+t[i];
          pq.push(make_pair(-dist[y],y));
        }
      }
    }
  }
  return -1;
}
int main(){
  read(n),read(m),read(st),read(ed);
  for(register int i=1;i<=m;++i){
    int u,v;ll w1,w2;
    read(u),read(v),read(w1),read(w2);
    Addedge(u,v,w1,w2);Addedge(v,u,w1,w2);
  }
  print(DJ());
  return 0;
}

#pragma warning(disable:4996)
//#include <bits/stdc++.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <string.h>
#include <queue>
#define fastio ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ln '\n'
#define rp ' '
typedef long long ll;
typedef long double lf;
using namespace std;
typedef struct Edge
{
	ll e, c, k;
};
typedef struct Node
{
	ll e, c;
	bool operator<(const Node tmp) const
	{
		return c > tmp.c;
	}
};
ll n, m, x, y;
ll dist[100100];
ll INF = 1e18;
priority_queue<Node> pq;
vector<Edge> map[100100];
void dijkstra()
{
	while (!pq.empty())
	{
		Node now = pq.top();
		pq.pop();
		if (now.c > dist[now.e]) continue;
		for (auto i : map[now.e])
		{
			if (dist[now.e] % i.k)
			{
				if (dist[i.e] > dist[now.e] + i.c + i.k - dist[now.e] % i.k)
				{
					dist[i.e] = dist[now.e] + i.c + i.k - dist[now.e] % i.k;
					pq.push({ i.e, dist[i.e] });
				}
			}
			else
			{
				if (dist[i.e] > dist[now.e] + i.c)
				{
					dist[i.e] = dist[now.e] + i.c;
					pq.push({ i.e, dist[i.e] });
				}
			}
		}
	}
}
int main()
{
	fastio;
	cin >> n >> m >> x >> y;
	for (ll i = 1; i <= m; i++)
	{
		ll a, b, t, k;
		cin >> a >> b >> t >> k;
		map[a].push_back({ b, t, k });
		map[b].push_back({ a, t, k });
	}
	fill(dist, dist + n + 1, INF);
	dist[x] = 0;
	pq.push({ x, 0 });
	dijkstra();
	if (dist[y] == INF) cout << -1;
	else cout << dist[y];
}