// Problem: E - Train
// Contest: AtCoder - AtCoder Beginner Contest 192
// URL: https://atcoder.jp/contests/abc192/tasks/abc192_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#define ll long long
#define mod 1000000007

// templates
#define all(v) v.begin(), v.end()
#define F first
#define S second
#define sz(x) (int)x.size()
#define po(x, y) fixed << setprecision(y) << x
#define ss(s) scanf(" %[^\n]%*c", s)
#define sc(n) scanf("%d", &n)
#define sl(n) scanf("%lld", &n)
#define ps(s) printf("%s\n", s)
#define pr(n) printf("%d\n", n)
#define pl(n) printf("%lld\n", n)
#define prs(n) printf("%d ", n)
#define pls(n) printf("%lld ", n)
using namespace std;

const ll inf = (ll)1e16 + 10;
const int N = (int)1e5 + 10;
int a[N], b[N];
vector<array<ll, 3>> adj[N];  // u->v,t,k
vector<ll> dist(N);
ll n, m, x, y;
void bfs() {
  set<array<ll, 2>> s;  // time,node
  s.insert({0, x});
  for (int i = 0; i <= n; i++) {
    dist[i] = inf;
  }
  dist[x] = 0;
  while (sz(s)) {
    auto temp = *s.begin();
    s.erase(s.begin());
    ll node = temp[1], kete = temp[0];
    for (auto c : adj[node]) {
      ll add = 0;
      if (kete < c[2] && kete != 0) {
        add = (c[2] - kete);
      } else if (kete != 0) {
        if (kete % c[2]) {
          add = c[2] - (kete % c[2]);
        }
      }
      ll curr = c[1] + add + kete;
      // printf("node-> %lld curr-> %lld\n", node, curr);
      if (dist[c[0]] > curr) {
        s.erase({dist[c[0]], c[0]});
        dist[c[0]] = curr;
        s.insert({curr, c[0]});
      }
    }
  }
  if (dist[y] == inf) {
    dist[y] = -1;
  }
  pl(dist[y]);
}
void solve() {
  sl(n), sl(m), sl(x), sl(y);
  for (int i = 1; i <= m; i++) {
    ll u, v, t, k;
    sl(u), sl(v), sl(t), sl(k);
    adj[u].push_back({v, t, k});
    adj[v].push_back({u, t, k});
  }
  bfs();
}

int main() {
  // #ifndef ONLINE_JUDGE
  // freopen("input.txt", "r", stdin);
  // freopen("output.txt", "w", stdout);
  // #endif
  int t = 1;
  // sc(t);
  while (t--) {
    solve();
  }
  // cerr << (float)clock() / CLOCKS_PER_SEC * 1000 << " ms" << endl;
  return 0;
}
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ss second
#define ff first
#define all(a) a.begin(), a.end()
#define All(a) a.rbegin(), a.rend()
#define ios ios_base::sync_with_stdio(0), cin.tie(0), cout.precision(10), cout << fixed
const int N = 2e5 + 5;
ll cost[N], n, m;
ll inf = 1e18;
struct dt {
    int u, cost, k;
    dt(int u, int cost, int k) {
        this->u = u;
        this->cost = cost;
        this->k = k;
    }
};
vector<dt> g[N];
void dijk(ll u) {
    priority_queue<pair<ll, ll>, vector<pair<ll, ll>>, greater<pair<ll, ll>>> q;
    for (int i = 0; i <= n; ++i)
        cost[i] = inf;
    cost[u] = 0;
    q.push({0, u});
    while (!q.empty()) {
        ll src = q.top().ss, cst = q.top().ff;
        q.pop();
        for (int i = 0; i < g[src].size(); ++i) {
            ll curr = g[src][i].u;
            ll tmp = (ll)ceil(cst / (double)g[src][i].k) * g[src][i].k + g[src][i].cost;
            if (tmp < cost[curr]) {
                cost[curr] = tmp;
                q.push({cost[curr], curr});
            }
        }
    }
}
int main() {
    ios;
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    int x, y;
    cin >> n >> m >> x >> y;
    x--;
    y--;
    for (int i = 0, a, b, c, d; i < m; ++i) {
        cin >> a >> b >> c >> d;
        a--;
        b--;
        g[a].push_back(dt(b, c, d));
        g[b].push_back(dt(a, c, d));
    }
    dijk(x);
    cout << (cost[y] == inf ? -1 : cost[y]) << '\n';
    return 0;
}
