#include <bits/stdc++.h>
using namespace std;
inline char nc() {
  return getchar();
  static char buf[100000], *l = buf, *r = buf;
  return l == r && (r = (l = buf) + fread(buf, 1, 100000, stdin), l == r)
             ? EOF
             : *l++;
}
template <class T>
void read(T &x) {
  x = 0;
  int f = 1, ch = nc();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = nc();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 - '0' + ch;
    ch = nc();
  }
  x *= f;
}
const int inf = 1e9 + 1;
const int maxn = 100 + 5;
const int maxs = 1e5 + 5;
const int maxb = 1e5 + 5;
int n, m;
int s, b, k;
int st, ed;
int val[maxn];
int dis[maxn][maxn];
int head[maxs];
vector<int> adj[maxn];
struct data {
  int a, b, c, d, id;
  inline bool operator<(const data &other) const { return b < other.b; }
} A[maxs], B[maxb];
struct edge {
  int to, nex;
  long long cap, flow;
  edge(int to = 0, int nex = 0, long long cap = 0, long long flow = 0)
      : to(to), nex(nex), cap(cap), flow(flow) {}
};
vector<edge> G;
inline void adde(int u, int v) {
  adj[u].push_back(v);
  adj[v].push_back(u);
}
inline void addedge(int u, int v, long long c) {
  G.push_back(edge(v, head[u], c, 0)), head[u] = G.size() - 1;
  G.push_back(edge(u, head[v], 0, 0)), head[v] = G.size() - 1;
}
namespace dinic {
int dis[maxs], cur[maxs];
bool BFS() {
  static int q[maxs];
  int hd = 0, tl = 0;
  memset(dis, -1, sizeof(dis));
  dis[st] = 0;
  q[tl++] = st;
  while (hd < tl) {
    int u = q[hd++];
    for (int i = head[u]; ~i; i = G[i].nex) {
      int v = G[i].to;
      if (dis[v] == -1 && G[i].cap != G[i].flow) {
        dis[v] = dis[u] + 1;
        q[tl++] = v;
      }
    }
  }
  return dis[ed] != -1;
}
long long DFS(int u, long long flow) {
  if (u == ed || flow == 0) return flow;
  long long rec = flow;
  for (int &i = cur[u]; ~i; i = G[i].nex) {
    int v = G[i].to;
    if (dis[v] == dis[u] + 1) {
      long long d = DFS(v, min(flow, G[i].cap - G[i].flow));
      G[i].flow += d;
      G[i ^ 1].flow -= d;
      flow -= d;
      if (flow == 0) break;
    }
  }
  return rec - flow;
}
long long maxflow() {
  long long flow = 0;
  while (BFS()) {
    memcpy(cur, head, sizeof(head));
    flow += DFS(st, 1e18);
  }
  return flow;
}
}  // namespace dinic
int adde(int x) {
  int mx = -1;
  for (int i = 1; i <= n; ++i)
    if (dis[A[x].a][i] <= A[x].c) {
      mx = max(mx, val[i]);
    }
  if (mx == -1) {
    addedge(A[x].id, ed, 1e18);
    return 0;
  }
  mx -= A[x].d;
  if (mx < 0) {
    addedge(A[x].id, ed, -mx);
    return 0;
  }
  addedge(st, A[x].id, mx);
  return mx;
}
void BFS(int st) {
  static int q[maxn];
  int hd = 0, tl = 0;
  for (int i = 1; i <= n; ++i) dis[st][i] = inf;
  dis[st][st] = 0;
  q[tl++] = st;
  while (hd < tl) {
    int u = q[hd++];
    for (unsigned int i = 0; i < adj[u].size(); ++i) {
      int v = adj[u][i];
      if (dis[st][v] == inf) {
        dis[st][v] = dis[st][u] + 1;
        q[tl++] = v;
      }
    }
  }
}
void init() {
  for (int i = 1; i <= n; ++i) BFS(i);
}
long long solve() {
  init();
  sort(A + 1, A + s + 1);
  sort(B + 1, B + b + 1);
  long long an = 0;
  int i = 1, j = 1;
  st = 0, ed = s + 1;
  memset(val, -1, sizeof(val));
  while (i <= s && j <= b) {
    if (B[j].b <= A[i].b) {
      val[B[j].a] = max(val[B[j].a], B[j].c);
      ++j;
    } else {
      an += adde(i++);
    }
  }
  while (i <= s) an += adde(i++);
  return an - dinic ::maxflow();
}
int main() {
  read(n), read(m);
  for (int i = 1; i <= m; ++i) {
    int u, v;
    read(u), read(v);
    adde(u, v);
  }
  read(s), read(b), read(k);
  for (int i = 1; i <= s; ++i) {
    read(A[i].a), read(A[i].b), read(A[i].c), read(A[i].d);
    A[i].id = i;
  }
  for (int i = 1; i <= b; ++i) {
    read(B[i].a), read(B[i].b), read(B[i].c);
  }
  memset(head, -1, sizeof(head));
  for (int i = 1; i <= k; ++i) {
    int s1, s2;
    read(s1), read(s2);
    addedge(s1, s2, 1e18);
  }
  printf("%I64d\n", solve());
  return 0;
}
