#include <bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
using vpii = vector<pii>;
using vi = vector<int>;
using vvi = vector<vi>;
using ll = long long;
using vll = vector<long long>;
template <class T>
using min_queue = priority_queue<T, vector<T>, greater<T>>;
template <class T>
istream &operator>>(istream &, vector<T> &);
template <class T>
ostream &operator<<(ostream &, const vector<T> &);
template <class T, class U>
istream &operator>>(istream &, pair<T, U> &);
template <class T, class U>
ostream &operator<<(ostream &, const pair<T, U> &);
template <class T>
struct Inf {
  static constexpr T inf() {
    return std::numeric_limits<T>::has_infinity()
               ? std::numeric_limits<T>::infinty()
               : std::numeric_limits<T>::max();
  }
};
template <>
struct Inf<int> {
  static constexpr int inf() { return 0x3f3f3f3f; }
};
template <>
struct Inf<long long> {
  static constexpr long long inf() { return 0x3f3f3f3f3f3f3f3fLL; }
};
constexpr int INF = Inf<int>::inf();
constexpr ll BINF = Inf<ll>::inf();
template <class T>
class Dinic {
 private:
  struct edge {
    int from, to;
    T cap;
    edge *rev;
    edge(int u, int v, T c) : from(u), to(v), cap(c), rev(nullptr) {}
  };
  static constexpr T INF = Inf<T>::inf();
  int n, s, t;
  std::vector<std::vector<edge *>> g;

 public:
  Dinic(int n, int s, int t) : n(n), s(s), t(t), g(n) {}
  ~Dinic() {
    for (auto v : g)
      for (edge *e : v) delete e;
  }
  void addEdge(int u, int v, T c) {
    edge *in = new edge(u, v, c);
    edge *out = new edge(v, u, 0);
    g[u].push_back(in);
    g[v].push_back(out);
    in->rev = out;
    out->rev = in;
  }
  T maxFlow() {
    T mxf = 0;
    std::vector<T> dist(n, INF), vis(n);
    std::function<T(int, T)> dfs = [&](int u, T fo) -> T {
      if (u == t) return fo;
      for (; vis[u] < int(g[u].size()); vis[u]++) {
        edge *e = g[u][vis[u]];
        int v = e->to;
        if (dist[v] != dist[u] + 1 || e->cap <= 0) continue;
        T foo = dfs(v, std::min(fo, e->cap));
        if (foo > 0) {
          e->cap -= foo;
          e->rev->cap += foo;
          return foo;
        }
      }
      return 0;
    };
    for (;;) {
      for (int i = 0; i < n; i++) dist[i] = INF, vis[i] = 0;
      std::queue<int> q;
      q.push(s);
      dist[s] = 0;
      while (!q.empty()) {
        int u = q.front();
        q.pop();
        if (u == t) break;
        for (edge *e : g[u]) {
          int v = e->to;
          if (e->cap > 0 && dist[v] == INF) {
            dist[v] = dist[u] + 1;
            q.push(v);
          }
        }
      }
      if (dist[t] == INF) break;
      while (T fo = dfs(s, INF)) mxf += fo;
    }
    return mxf;
  }
};
template <class T>
constexpr T Dinic<T>::INF;
int solve() {
  int n, m;
  cin >> n >> m;
  vvi dp(n, vi(n, INF));
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    u--, v--;
    dp[u][v] = dp[v][u] = 1;
  }
  for (int i = 0; i < n; i++) dp[i][i] = 0;
  for (int k = 0; k < n; k++)
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++) dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
  int s, b, k;
  cin >> s >> b >> k;
  vi xs(s), as(s), fs(s), ps(s), xb(b), db(b), gb(b);
  for (int i = 0; i < s; i++) {
    cin >> xs[i] >> as[i] >> fs[i] >> ps[i];
    xs[i]--;
  }
  for (int i = 0; i < b; i++) {
    cin >> xb[i] >> db[i] >> gb[i];
    xb[i]--;
  }
  vll canGet(s, -BINF);
  vector<vpii> bsList(n);
  for (int i = 0; i < b; i++) bsList[xb[i]].emplace_back(db[i], gb[i]);
  for (int i = 0; i < n; i++) {
    sort(bsList[i].begin(), bsList[i].end());
    int z = bsList[i].size();
    for (int j = 1; j < z; j++)
      bsList[i][j].second = max(bsList[i][j].second, bsList[i][j - 1].second);
  }
  for (int i = 0; i < s; i++)
    for (int j = 0; j < n; j++) {
      if (dp[xs[i]][j] > fs[i]) continue;
      auto it =
          upper_bound(bsList[j].begin(), bsList[j].end(), pii{as[i], INF});
      if (it == bsList[j].begin()) continue;
      it--;
      canGet[i] = max(canGet[i], ll(it->second));
    }
  for (int i = 0; i < s; i++) canGet[i] -= ps[i];
  ll ans = 0;
  Dinic<ll> g(s + 2, s, s + 1);
  for (int i = 0; i < s; i++) {
    if (canGet[i] >= 0) {
      ans += canGet[i];
      g.addEdge(s, i, canGet[i]);
    } else {
      g.addEdge(i, s + 1, -canGet[i]);
    }
  }
  for (int i = 0; i < k; i++) {
    int u, v;
    cin >> u >> v;
    u--, v--;
    g.addEdge(u, v, BINF);
  }
  ans -= g.maxFlow();
  cout << ans << endl;
  return 0;
}
int main() {
  ios::sync_with_stdio(0);
  solve();
  return 0;
}
template <class T>
istream &operator>>(istream &is, vector<T> &v) {
  for (auto it = v.begin(); it != v.end(); ++it) is >> *it;
  return is;
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (auto it = v.begin(); it != v.end();)
    os << *it, os << " \n"[++it == v.end()];
  return os;
}
template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ' ' << p.second;
}
