#include <bits/stdc++.h>
using namespace std;
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
const int MAXN = 100;
const int MAXSHIP = 100000;
const int MAXBASE = 100000;
const int MAXDEP = 1000;
const int MAXGN = 2 + MAXSHIP;
const int MAXGM = MAXSHIP + MAXDEP;
typedef struct MF {
  int n, m;
  int ghead[MAXGN], gnxt[2 * MAXGM], gto[2 * MAXGM];
  long long gcap[2 * MAXGM];
  void init(int _n) {
    n = _n, m = 0;
    for (int i = (0); i < (n); ++i) ghead[i] = -1;
  }
  void addedge(int a, int b, long long c) {
    gnxt[2 * m + 0] = ghead[a], ghead[a] = 2 * m + 0, gto[2 * m + 0] = b,
                 gcap[2 * m + 0] = c;
    gnxt[2 * m + 1] = ghead[b], ghead[b] = 2 * m + 1, gto[2 * m + 1] = a,
                 gcap[2 * m + 1] = 0;
    ++m;
  }
  int d[MAXGN];
  int q[MAXGN], qhead, qtail;
  int cur[MAXGN];
  long long dinic(int s, int t) {
    long long ret = 0;
    int niter = 0;
    while (true) {
      for (int i = (0); i < (n); ++i) d[i] = INT_MAX;
      qhead = qtail = 0;
      d[s] = 0, q[qhead++] = s;
      while (qtail < qhead && d[t] == INT_MAX) {
        int at = q[qtail++];
        for (int x = ghead[at]; x != -1; x = gnxt[x]) {
          int to = gto[x];
          if (gcap[x] == 0 || d[to] != INT_MAX) continue;
          d[to] = d[at] + 1;
          q[qhead++] = to;
        }
      }
      if (d[t] == INT_MAX) return ret;
      for (int i = (0); i < (n); ++i) cur[i] = ghead[i];
      ret += dfs(s, t, LLONG_MAX);
      ++niter;
    }
  }
  long long dfs(int at, int t, long long rem) {
    long long ret = 0;
    if (at == t) return rem;
    if (d[at] >= d[t]) return 0;
    for (; cur[at] != -1; cur[at] = gnxt[cur[at]]) {
      int to = gto[cur[at]];
      long long cap = gcap[cur[at]];
      if (d[to] != d[at] + 1 || cap == 0) continue;
      long long now = dfs(to, t, min(cap, rem));
      rem -= now;
      ret += now;
      if (gcap[cur[at]] != LLONG_MAX) gcap[cur[at]] -= now;
      if (gcap[cur[at] ^ 1] != LLONG_MAX) gcap[cur[at] ^ 1] += now;
      if (rem == 0) return ret;
    }
    return ret;
  }
} MF;
MF g;
struct Ship {
  int pos, attack, fuel, cost;
};
struct Base {
  int pos, defense, gold;
};
bool operator<(const Base &a, const Base &b) {
  if (a.gold != b.gold) return a.gold > b.gold;
  return a.defense < b.defense;
}
int n, m;
int d[MAXN][MAXN];
int nship, nbase, ndep;
Ship ship[MAXSHIP];
Base base[MAXBASE];
vector<int> dep[MAXSHIP];
vector<Base> opt[MAXN];
long long best[MAXSHIP];
vector<int> rdep[MAXSHIP];
bool alive[MAXSHIP];
int q[MAXSHIP], qhead, qtail;
int nid, sid, tid, shipid[MAXSHIP];
long long solve() {
  for (int i = (0); i < (nbase); ++i) opt[base[i].pos].push_back(base[i]);
  for (int i = (0); i < (n); ++i) sort(opt[i].begin(), opt[i].end());
  for (int i = (0); i < (n); ++i) {
    int nsz = 0;
    for (int j = (0); j < (((int)(opt[i]).size())); ++j)
      if (nsz == 0 || opt[i][j].defense < opt[i][nsz - 1].defense)
        opt[i][nsz++] = opt[i][j];
    opt[i].resize(nsz);
  }
  for (int i = (0); i < (nship); ++i) best[i] = LLONG_MIN;
  for (int i = (0); i < (nship); ++i)
    for (int j = (0); j < (n); ++j)
      if (d[ship[i].pos][j] <= ship[i].fuel && ((int)(opt[j]).size()) > 0 &&
          ship[i].attack >= opt[j].back().defense) {
        int l = -1, r = ((int)(opt[j]).size()) - 1;
        while (l + 1 < r) {
          int m = l + (r - l) / 2;
          if (ship[i].attack >= opt[j][m].defense)
            r = m;
          else
            l = m;
        }
        best[i] = max(best[i], (long long)opt[j][r].gold - ship[i].cost);
      }
  for (int i = (0); i < (nship); ++i)
    for (int j = (0); j < (((int)(dep[i]).size())); ++j) {
      int k = dep[i][j];
      rdep[k].push_back(i);
    }
  qhead = qtail = 0;
  for (int i = (0); i < (nship); ++i) {
    alive[i] = best[i] != LLONG_MIN;
    if (!alive[i]) q[qhead++] = i;
  }
  while (qtail < qhead) {
    int at = q[qtail++];
    for (int i = (0); i < (((int)(rdep[at]).size())); ++i) {
      int to = rdep[at][i];
      if (alive[to]) alive[to] = false, q[qhead++] = to;
    }
  }
  nid = 0, sid = nid++, tid = nid++;
  for (int i = (0); i < (nship); ++i)
    if (!alive[i])
      shipid[i] = -1;
    else
      shipid[i] = nid++;
  g.init(nid);
  long long sum = 0;
  for (int i = (0); i < (nship); ++i)
    if (alive[i]) {
      if (best[i] > 0) sum += best[i], g.addedge(sid, shipid[i], best[i]);
      if (best[i] < 0) g.addedge(shipid[i], tid, -best[i]);
    }
  for (int i = (0); i < (nship); ++i)
    for (int j = (0); j < (((int)(dep[i]).size())); ++j) {
      int k = dep[i][j];
      if (!alive[i]) continue;
      assert(alive[k]);
      g.addedge(shipid[i], shipid[k], LLONG_MAX);
    }
  long long flow = g.dinic(sid, tid);
  return sum - flow;
}
void run() {
  scanf("%d%d", &n, &m);
  for (int i = (0); i < (n); ++i)
    for (int j = (0); j < (n); ++j) d[i][j] = i == j ? 0 : INT_MAX;
  for (int i = (0); i < (m); ++i) {
    int a, b;
    scanf("%d%d", &a, &b);
    --a, --b;
    d[a][b] = min(d[a][b], 1);
    d[b][a] = min(d[b][a], 1);
  }
  for (int k = (0); k < (n); ++k)
    for (int i = (0); i < (n); ++i)
      for (int j = (0); j < (n); ++j)
        if (d[i][k] != INT_MAX && d[k][j] != INT_MAX)
          d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
  scanf("%d%d%d", &nship, &nbase, &ndep);
  for (int i = (0); i < (nship); ++i)
    scanf("%d%d%d%d", &ship[i].pos, &ship[i].attack, &ship[i].fuel,
          &ship[i].cost),
        --ship[i].pos;
  for (int i = (0); i < (nbase); ++i)
    scanf("%d%d%d", &base[i].pos, &base[i].defense, &base[i].gold),
        --base[i].pos;
  for (int i = (0); i < (ndep); ++i) {
    int a, b;
    scanf("%d%d", &a, &b);
    --a, --b;
    dep[a].push_back(b);
  }
  printf("%lld\n", solve());
}
int main() {
  run();
  return 0;
}
