#include<bits/stdc++.h>
#define pb push_back
#define Int long long
using namespace std;

long long N,M,K;
long long h,w;
long long X,Y,Z;
long long B;


const int MOD=1e9+7;

const int MAXN=5e5+5;
const int NAX=1005;
//vector<int> adj[MAXN];
vector<array<int,3>> adj[MAXN];
vector<Int> A;

Int ceilS(Int x,Int y){
    return (x+y-1)/y;
}

Int perform(Int x){
    return (x*(x+1))/2LL;
}


long long ModExpo(long long x,unsigned long long y,long long M){
    Int ans=1;
    ans=(long long)ans;
    
    while(y>0){
        if(y&1) ans=((ans%M)*(x%M))%M;
        y>>=1LL;
        x=((x%M)*(x%M))%M;
    }
    return ans%M;
}

long long ModInv(long long x){
    return ModExpo(x,MOD-2,MOD);
}
Int madd(Int x,Int y){
    return (x+y)%MOD;
}

Int mmul(Int x,Int y){
    return ((x%MOD)*(y%MOD))%MOD;
}
vector<long long> fac(MAXN);

Int performMod(Int x){
    return mmul(mmul(x,x+1),ModInv(2))%MOD;
}

void fill(){
    fac[0]=1;
    for(int i=1;i<MAXN;++i){
        fac[i]=mmul(fac[i-1],i)%MOD;
    }
}
long long choose(long long n,long long r){
    if(r==0||r==n) return 1;
    if(r>n) return 0;

    return mmul(mmul(fac[n],ModInv(fac[n-r])),ModInv(fac[r]))%MOD;
}


const int INF=1e9;
using D=long double;

vector<pair<int64_t,int64_t>> factorize(int64_t x){

    vector<pair<int64_t,int64_t>> factors;

    for(int64_t i=2;i*i<=x;++i){
        if(x % i) continue;
        int cnt=0;

        while(x % i ==0){
            x/=i;
            ++cnt;
        }
        factors.pb({i,cnt});
    }
    if(x > 1){
        factors.pb({x,1});
    }
    return factors;
}


struct TreeNode{
    int data;
    struct TreeNode* children[2];

    TreeNode(int x){
        data=x;
        for(int i=0;i<2;++i){
            children[i]=nullptr;
        }
    }
};

TreeNode* recur(int l,int r){
    if(r < l)  return nullptr;
    if(l==r){
        return new TreeNode(A[l]);
    }

    int mx=0,idx;
    for(int i=l;i<=r;++i){
        if(mx < A[i]){
            mx=A[i];
            idx=i;
        }
    }

    TreeNode* root=new TreeNode(mx);
    root->children[0]=recur(l,idx-1);
    root->children[1]=recur(idx+1,r);
    return root;

}

vector<int> depth;
void Preorder(TreeNode *root,int lvl){
    if(!root) return;

    depth[root->data]=lvl;

    Preorder(root->children[0],lvl+1);
    Preorder(root->children[1],lvl+1);
}



int main()
{

    ios_base::sync_with_stdio(false);cin.tie(0);
    cout.tie(0);

    cin>>N>>M>>X>>Y;
    for(int i=0;i<M;++i){
        int u,v,w,k;
        cin>>u>>v>>w>>k;
        --u;--v;
        adj[u].pb({v,w,k});
        adj[v].pb({u,w,k});
    }

    auto merge=[&](int64_t x,int64_t k){
            if(x % k==0) return 0LL;
            return (k - (x%k))*1LL;
            
        };


    auto dijkstra=[&](int src,int d){
        
        vector<int64_t> dis(N,1e15);
        
        priority_queue<array<int64_t,3>,vector<array<int64_t,3>>,greater<array<int64_t,3>>> pq;
       
        dis[src]=0;
        pq.push({dis[src],src,0});

        while(!pq.empty()){
            auto u=pq.top();
            pq.pop();
    
            if(dis[u[1]] < u[0]) continue;
            for(auto &v:adj[u[1]]){
                if(dis[u[1]] + v[1] +merge(dis[u[1]],v[2]) < dis[v[0]]){
                    dis[v[0]]=dis[u[1]] + v[1] + merge(dis[u[1]],v[2]);
                    pq.push({dis[v[0]],v[0],merge(dis[u[1]],v[2])});
                }
            }

        }

        cout<<(dis[d]==1e15 ? -1:dis[d])<<'\n';
    };

    dijkstra(--X,--Y);



    
}
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
#define int long long
const int N = 2e5+10;
typedef pair<int, int> pii;
struct E{
  int v,t,k;
};
vector<E> e[N];
int n, m;
int dis[N];
bool vis[N];

void dijkstra(int s) {
  memset(dis, 0x3f, sizeof dis);
  dis[s] = 0;
  priority_queue<pii, vector<pii>, greater<pii>> q;
  q.push({0, s});
  while (!q.empty()) {
    auto t = q.top(); q.pop();
    int u = t.second, distance = t.first;
    if (vis[u]) continue;
    vis[u] = true;
    for (auto to: e[u]) {
      int v = to.v, t = to.t, k = to.k;
      int W = (distance + k - 1) / k * k + t;
      if (dis[v] > W) {
        dis[v] = W;
        q.push({dis[v], v});
      }
    }
  }
}

signed main() {
  int A, B;
  scanf("%lld%lld%lld%lld",&n,&m,&A,&B);
  while (m--) {
    int u, v, t, k;
    scanf("%lld%lld%lld%lld",&u,&v,&t,&k);
    e[u].push_back({v, t, k});
    e[v].push_back({u, t, k});
  }
  dijkstra(A);
  int ans = dis[B];
  if (ans == 0x3f3f3f3f3f3f3f3f) ans = -1;
  printf("%lld\n",ans);
  return 0;
}