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

int main() {
  int h, w, n, m;
  cin >> h >> w >> n >> m;
  map<P, int> ab;
  rep(i, 0, n) {
    int a, b;
    cin >> a >> b;
    ab[P(a - 1, b - 1)] = 0;
  }
  map<P, int> cd;
  rep(i, 0, m) {
    int c, d;
    cin >> c >> d;
    cd[P(c - 1, d - 1)] = 0;
  }
  Field(bool) yoko(h, vector<bool>(w, false));
    bool l = false;
  rep(i, 0, h) {
    int s = 0;
    l = false;
    rep(j, 0, w) {
      if (ab.find(P(i, j)) != ab.end()) {
        rep(k, s, j + 1) {
          yoko[i][k] = true;
        }
        l = true;
        s = j + 1;
      } else if (cd.find(P(i, j)) != cd.end()) {
        if (l) {
          l = false;
          rep(k, s, j) { yoko[i][k] = true; }
          s = j + 1;
        } else {
          rep(k, s, j) { yoko[i][k] = false; }
          s = j + 1;
        }
      }
    }
    if (l) {
      rep(k, s, w) {
        yoko[i][k] = true;
      }
    }
  }
  Field(bool) tate(h, vector<bool>(w, false));
  l = false;
  rep(i, 0, w) {
    int s = 0;
    l = false;
    rep(j, 0, h) {
      if (ab.find(P(j, i)) != ab.end()) {
        rep(k, s, j + 1) {
          tate[k][i] = true;
          l = true;
        }
        s = j + 1;
      } else if (cd.find(P(j, i)) != cd.end()) {
        if (l) {
          l = false;
          rep(k, s, j) { tate[k][i] = true; }
          s = j + 1;
        } else {
          rep(k, s, j) { tate[k][i] = false; }
          s = j + 1;
        }
      }
    }
    if (l) {
      rep(k, s, h) {
        tate[k][i] = true;
      }
    }
  }
  int ans = 0;
  rep(i,0,h) rep(j,0,w){
    if (yoko[i][j] || tate[i][j]) ans++;
  }
  cout << ans << endl;
  return 0;
}

template <class T>
inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
#include <bits/stdc++.h>
// #include <atcoder/modint>
#define rng(a) a.begin(),a.end()
#define rrng(a) a.rbegin(),a.rend()
#define INF 2000000000000000000
#define ll long long
#define ld long double
#define pll pair<ll, ll>
using namespace std;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }

struct edge {ll to, cost, k;};
//=============dijkstra============================
vector<ll> dijkstra(ll s, ll V, vector<vector<edge>>& G)
{
  vector<ll> d(V, INF);
  typedef pair<ll, ll> P;// first は最短距離　second は頂点の番号
  priority_queue<P, vector<P>, greater<P>> que;
  d.at(s) = 0;
  que.push(P(0, s));
  while (!que.empty())
  {
    P p = que.top();
    que.pop();
    ll v = p.second;
    if (d.at(v) < p.first) continue;
    for (ll i = 0; i < G.at(v).size(); ++i)
    {
      edge e = G.at(v).at(i);
      if (d.at(e.to) > ((d.at(v) + e.k - 1) / e.k) * e.k + e.cost)
      {
        d.at(e.to) = ((d.at(v) + e.k - 1) / e.k) * e.k + e.cost;
        que.push(P(d.at(e.to), e.to));
      }
    }
  }
  return d;
}
//=================================================

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  ll N, M, X, Y;
  cin >> N >> M >> X >> Y;
  X -= 1, Y -= 1;
  vector<vector<edge>> connection(N);
  for (ll i = 0; i < M; ++i) {
    ll a, b, t, k;
    cin >> a >> b >> t >> k;
    a -= 1, b -= 1;
    connection.at(a).push_back({b, t, k});
    connection.at(b).push_back({a, t, k});
  }
  vector<ll> d = dijkstra(X, N, connection);
  if (d.at(Y) == INF) {
    cout << -1 << "\n";
  }
  else {
    cout << d.at(Y) << "\n";
  }
}
