#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-9;
const long long oo = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
int dist[128][128];
struct ss {
  int x, a, f, p;
} SS[100000];
long long best[100000];
vector<pair<int, int>> BASE[128];
template <typename flow_type>
struct dinic {
  struct edge {
    size_t src, dst, rev;
    flow_type flow, cap;
  };
  int n;
  vector<vector<edge>> adj;
  dinic(int n) : n(n), adj(n), level(n), q(n), it(n) {}
  void add_edge(size_t src, size_t dst, flow_type cap, flow_type rcap = 0) {
    adj[src].push_back({src, dst, adj[dst].size(), 0, cap});
    if (src == dst) adj[src].back().rev++;
    adj[dst].push_back({dst, src, adj[src].size() - 1, 0, rcap});
  }
  vector<int> level, q, it;
  bool bfs(int source, int sink) {
    fill(level.begin(), level.end(), -1);
    for (int qf = level[q[0] = sink] = 0, qb = 1; qf < qb; ++qf) {
      sink = q[qf];
      for (edge &e : adj[sink]) {
        edge &r = adj[e.dst][e.rev];
        if (r.flow < r.cap && level[e.dst] == -1)
          level[q[qb++] = e.dst] = 1 + level[sink];
      }
    }
    return level[source] != -1;
  }
  flow_type augment(int source, int sink, flow_type flow) {
    if (source == sink) return flow;
    for (; it[source] != adj[source].size(); ++it[source]) {
      edge &e = adj[source][it[source]];
      if (e.flow < e.cap && level[e.dst] + 1 == level[source]) {
        flow_type delta = augment(e.dst, sink, min(flow, e.cap - e.flow));
        if (delta > 0) {
          e.flow += delta;
          adj[e.dst][e.rev].flow -= delta;
          return delta;
        }
      }
    }
    return 0;
  }
  flow_type max_flow(int source, int sink) {
    for (int u = 0; u < n; ++u)
      for (edge &e : adj[u]) e.flow = 0;
    flow_type flow = 0;
    flow_type oo = numeric_limits<flow_type>::max();
    while (bfs(source, sink)) {
      fill(it.begin(), it.end(), 0);
      for (flow_type f; (f = augment(source, sink, oo)) > 0;) flow += f;
    }
    return flow;
  }
};
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  memset(dist, 0x3f, sizeof dist);
  for (int i = 0; i < m; ++i) {
    int u, v;
    cin >> u >> v;
    u--;
    v--;
    dist[u][v] = dist[v][u] = 1;
  }
  for (int i = 0; i < n; ++i) dist[i][i] = 0;
  for (int k = 0; k < n; ++k)
    for (int i = 0; i < n; ++i)
      for (int j = 0; j < n; ++j) {
        dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
      }
  int s, b, k;
  cin >> s >> b >> k;
  for (int i = 0; i < s; ++i) {
    cin >> SS[i].x >> SS[i].a >> SS[i].f >> SS[i].p;
    SS[i].x--;
    best[i] = -oo;
  }
  for (int i = 0; i < b; ++i) {
    int x, d, g;
    cin >> x >> d >> g;
    x--;
    BASE[x].push_back({d, g});
  }
  for (int i = 0; i < n; ++i) {
    sort(BASE[i].begin(), BASE[i].end());
    vector<pair<int, int>> inc;
    for (auto p : BASE[i]) {
      if (inc.empty() || p.second > inc.back().second) {
        inc.push_back(p);
      }
    }
    for (int j = 0; j < s; ++j) {
      if (SS[j].f < dist[SS[j].x][i]) continue;
      int p =
          upper_bound(inc.begin(), inc.end(), pair<int, int>(SS[j].a, mod)) -
          inc.begin();
      if (p) {
        --p;
        best[j] = max(best[j], 1LL * (inc[p].second - SS[j].p));
      }
    }
  }
  dinic<long long> closure(s + 2);
  for (int i = 0; i < k; ++i) {
    int u, v;
    cin >> u >> v;
    u--;
    v--;
    closure.add_edge(u + 2, v + 2, oo);
  }
  long long positive = 0;
  for (int i = 0; i < s; ++i) {
    if (best[i] >= 0) {
      positive += best[i];
      closure.add_edge(0, i + 2, best[i]);
    } else {
      closure.add_edge(i + 2, 1, -best[i]);
    }
  }
  long long cut = closure.max_flow(0, 1);
  cout << positive - cut << '\n';
  return 0;
}
