#include <bits/stdc++.h>
#define fi first
#define se second
#define rep(i,s,n) for (int i = (s); i < (n); ++i)
#define rrep(i,n,g) for (int i = (n)-1; i >= (g); --i)
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define len(x) (int)(x).size()
#define dup(x,y) (((x)+(y)-1)/(y))
#define pb push_back
#define eb emplace_back
#define Field(T) vector<vector<T>>
#define pq(T) priority_queue<T,vector<T>,greater<T>>
using namespace std;
using ll = long long;
using P = pair<int,int>;

int main() {
  int a, b, c, d;
  cin >> a >> b >> c >> d;
  cout << min({a, b, c, d}) << endl;
  return 0;
}
#include <bits/stdc++.h>
using namespace std;

#define MAXN 200005
typedef long long ll;
typedef unsigned long long ull;

ull Max = 0x3f3f3f3f3f3f3f3f;

ull dist[MAXN];
typedef struct
{
    ull to;
    ull t, k;
} Node;
vector<Node> vec[MAXN];
ull N, M, X, Y;

void min_len2()
{
    using Pair = pair<ull, ull>;

    for (ull i = 1; i <= N; i++)
        dist[i] = Max;
    dist[X] = 0;

    priority_queue<Pair, vector<Pair>, greater<Pair>> q; // 小根堆
    q.push(Pair(0, X));

    while (!q.empty())
    {
        auto top = q.top();
        auto tick = top.first;
        auto node = top.second;

        if (node == Y && tick != 0)
            return;

        q.pop();

        for (auto &x : vec[node])
        {
            ull d = tick + (x.k - tick % x.k) % x.k + x.t; // dist + wait + travel time
            if (d < dist[x.to])
            {
                dist[x.to] = d;
                q.push(Pair(dist[x.to], x.to));
            }
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin >> N >> M >> X >> Y;

    for (ull i = 0; i < M; i++)
    {
        ull a, b, t, k;
        cin >> a >> b >> t >> k;
        vec[a].push_back({b, t, k});
        vec[b].push_back({a, t, k});
    }
    min_len2();

    if (dist[Y] >= Max)
        cout << "-1" << endl;
    else
        cout << dist[Y] << endl;

    return 0;
}