#include <bits/stdc++.h>
using namespace std;
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  long long n, m;
  cin >> n >> m;
  vector<vector<long long>> dist((size_t)n,
                                 vector<long long>((size_t)n, (long long)1e16));
  for (long long i = 0; i < n; i++) {
    dist[i][i] = (long long)0;
  }
  for (long long i = 0; i < m; i++) {
    long long u, v;
    cin >> u >> v;
    u--, v--;
    dist[u][v] = dist[v][u] = 0;
  }
  for (long long k = 0; k < n; k++) {
    for (long long i = 0; i < n; i++) {
      for (long long j = 0; j < n; j++) {
        dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
      }
    }
  }
  long long s, b, k;
  cin >> s >> b >> k;
  vector<tuple<long long, long long, long long, long long>> x((size_t)s);
  for (long long i = 0; i < s; i++) {
    cin >> get<0>(x[i]) >> get<1>(x[i]) >> get<2>(x[i]) >> get<3>(x[i]);
    get<0>(x[i])--;
  }
  vector<tuple<long long, long long, long long>> y((size_t)b);
  for (long long i = 0; i < b; i++) {
    cin >> get<0>(y[i]) >> get<1>(y[i]) >> get<2>(y[i]);
    get<0>(y[i])--;
  }
  vector<map<long long, long long>> bases((size_t)n);
  for (long long i = 0; i < b; i++) {
    bases[get<0>(y[i])][get<1>(y[i])] = get<2>(y[i]);
  }
  for (long long i = 0; i < n; i++) {
    for (auto j = bases[i].begin(); j != bases[i].end();) {
      if (j == bases[i].begin() || j->second > prev(j)->second) {
        j++;
      } else {
        j = bases[i].erase(j);
      }
    }
  }
  vector<long long> damages((size_t)s, (long long)-1e16);
  for (long long i = 0; i < s; i++) {
    for (long long j = 0; j < n; j++) {
      if (get<2>(x[i]) >= dist[get<0>(x[i])][j]) {
        auto it = bases[j].upper_bound(get<1>(x[i]));
        if (it != bases[j].begin()) {
          damages[i] = max(damages[i], prev(it)->second - get<3>(x[i]));
        }
      }
    }
  }
  vector<vector<long long>> init_adj((size_t)s), init_adj_rev((size_t)s);
  vector<vector<pair<long long, long long>>> adj((size_t)s + 2);
  vector<map<long long, long long>> flows((size_t)s + 2);
  auto add_edge = [&](long long u, long long v, long long w) {
    adj[u].emplace_back(v, w);
    adj[v].emplace_back(u, 0);
    flows[u][v] = 0;
    flows[v][u] = 0;
  };
  for (long long i = 0; i < k; i++) {
    long long u, v;
    cin >> u >> v;
    u--, v--;
    if (u != v) {
      init_adj[u].push_back(v);
      init_adj_rev[v].push_back(u);
      add_edge(u, v, (long long)1e16);
    }
  }
  long long o = 0;
  for (long long u = 0; u < s; u++) {
    o += max(damages[u], (long long)0);
    if (damages[u] > 0) {
      if (!init_adj[u].empty()) {
        add_edge(s, u, damages[u]);
      }
    } else {
      if (!init_adj_rev[u].empty()) {
        add_edge(u, s + 1, -damages[u]);
      }
    }
  }
  vector<bool> visited;
  vector<long long> path;
  function<long long(long long)> visit = [&](long long u) {
    if (!visited[u]) {
      visited[u] = true;
      path.push_back(u);
      if (u == s + 1) {
        return (long long)1e16;
      } else {
        for (auto [v, w] : adj[u]) {
          if (w - flows[u][v] > 0) {
            long long a = visit(v);
            if (a > 0) {
              return min(w - flows[u][v], a);
            }
          }
        }
      }
      path.pop_back();
    }
    return (long long)0;
  };
  while (true) {
    visited.assign((long long)s + 2, false);
    path.clear();
    long long a = visit(s);
    if (a > 0) {
      for (long long i = 1; i < (long long)path.size(); i++) {
        flows[path[i - 1]][path[i]] += a;
        flows[path[i]][path[i - 1]] -= a;
      }
      o -= a;
    } else {
      break;
    }
  }
  cout << o << endl;
  return 0;
}
