#include <bits/stdc++.h>
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
using namespace std;
const long long INF = 0x3f3f3f3f3f3f3f3fll;
const double eps = 1e-9;
template <typename T>
typename enable_if<!is_integral<T>::value, void>::type read(T &x) {
  cin >> x;
}
long long read() {
  char c;
  long long out = 0, f = 1;
  for (c = getchar(); !isdigit(c) && c != '-'; c = getchar())
    ;
  if (c == '-') {
    f = -1;
    c = getchar();
  }
  for (; isdigit(c); c = getchar()) out = (out << 3) + (out << 1) + c - '0';
  return out * f;
}
template <typename T>
typename enable_if<is_integral<T>::value, T>::type read(T &x) {
  char c;
  T f = 1;
  x = 0;
  for (c = getchar(); !isdigit(c) && c != '-'; c = getchar())
    ;
  if (c == '-') {
    f = -1;
    c = getchar();
  }
  for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
  return x *= f;
}
char read(char &x) {
  for (x = getchar(); isspace(x); x = getchar())
    ;
  return x;
}
double read(double &x) {
  scanf("%lf", &x);
  return x;
}
void read(char *x) { scanf("%s", x); }
template <typename T>
typename enable_if<!is_integral<T>::value, void>::type write(const T &x) {
  cout << x;
}
template <typename T>
typename enable_if<is_integral<T>::value, void>::type write(const T &x) {
  if (x < 0) {
    putchar('-');
    write(-x);
    return;
  }
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
void write(const char &x) { putchar(x); }
void write(const double &x) { printf("%.10lf", x); }
void write(const char *x) { printf("%s", x); }
template <typename T, typename... Args>
void read(T &x, Args &...args) {
  read(x);
  read(args...);
}
template <typename... Args>
void read(char *x, Args &...args) {
  read(x);
  read(args...);
}
template <
    typename OutputIt,
    typename = typename enable_if<
        is_same<output_iterator_tag,
                typename iterator_traits<OutputIt>::iterator_category>::value ||
        (is_base_of<forward_iterator_tag, typename iterator_traits<OutputIt>::
                                              iterator_category>::value &&
         !is_const<OutputIt>::value)>::type>
void read(OutputIt __first, OutputIt __last) {
  for (; __first != __last; ++__first) read(*__first);
}
template <
    typename InputIt,
    typename = typename enable_if<is_base_of<
        input_iterator_tag,
        typename iterator_traits<InputIt>::iterator_category>::value>::type>
void wts(InputIt __first, InputIt __last) {
  for (; __first != __last; ++__first) {
    write(*__first);
    putchar(' ');
  }
}
template <
    typename InputIt,
    typename = typename enable_if<is_base_of<
        input_iterator_tag,
        typename iterator_traits<InputIt>::iterator_category>::value>::type>
void wtb(InputIt __first, InputIt __last) {
  for (; __first != __last; ++__first) {
    write(*__first);
    putchar('\n');
  }
}
void wts(const char *x) {
  write(x);
  putchar(' ');
}
void wtb(const char *x) {
  write(x);
  putchar('\n');
}
template <typename T>
void wts(const T &x) {
  write(x);
  putchar(' ');
}
template <typename T>
void wtb(const T &x) {
  write(x);
  putchar('\n');
}
template <typename... Args>
void wts(const char *x, Args... args) {
  wts(x);
  wts(args...);
}
template <typename... Args>
void wtb(const char *x, Args... args) {
  wts(x);
  wtb(args...);
}
template <typename T, typename... Args>
void wts(const T &x, Args... args) {
  wts(x);
  wts(args...);
}
template <typename T, typename... Args>
void wtb(const T &x, Args... args) {
  wts(x);
  wtb(args...);
}
template <typename T>
inline bool up(T &x, const T &y) {
  return x < y ? x = y, 1 : 0;
}
template <typename T>
inline bool dn(T &x, const T &y) {
  return y < x ? x = y, 1 : 0;
}
const long long N = 110;
const long long S = 1010;
const long long mod = 1000000007;
queue<long long> q;
long long head[S << 1], cur[S << 1], nxt[S * S * 2], to[S * S * 2],
    edge[S * S * 2], cnt = 1;
long long n, m, c, b, k, h, x[S], a[S], f[S], y[S], d[S], dis[N][N],
    dep[S << 1], qwq = S * 2 - 3, s = S * 2 - 2, t = S * 2 - 1;
void add(long long u, long long v, long long w) {
  nxt[++cnt] = head[u];
  head[u] = cnt;
  to[cnt] = v;
  edge[cnt] = w;
}
void Add(long long u, long long v, long long w) {
  add(u, v, w);
  add(v, u, 0);
}
long long dfs(long long u, long long flow) {
  if (dep[u] == dep[t]) return u == t ? flow : 0;
  long long v, w, f, out = 0;
  for (long long &i = cur[u]; i && flow - out; i = nxt[i]) {
    v = to[i];
    w = edge[i];
    if (w > 0 && dep[v] == dep[u] + 1) {
      f = dfs(v, min(w, flow - out));
      edge[i] -= f;
      edge[i ^ 1] += f;
      out += f;
    }
  }
  return out;
}
bool bfs() {
  memset(dep, -1, sizeof(dep));
  dep[s] = 0;
  q.push(s);
  while (!q.empty()) {
    long long u = q.front();
    q.pop();
    for (long long i = head[u]; i; i = nxt[i]) {
      long long v = to[i];
      long long w = edge[i];
      if (w > 0 && dep[v] == -1) {
        dep[v] = dep[u] + 1;
        q.push(v);
      }
    }
  }
  return dep[t] > 0;
}
long long dinic() {
  long long out = 0;
  while (bfs()) {
    memcpy(cur, head, sizeof(cur));
    out += dfs(s, INF);
  }
  return out;
}
signed main() {
  read(n, m);
  memset(dis, 0x3f, sizeof(dis));
  for (long long i = (1), iend = (m); i <= iend; ++i) {
    long long u, v;
    read(u, v);
    dis[u][v] = dis[v][u] = 1;
  }
  for (long long i = (1), iend = (n); i <= iend; ++i) dis[i][i] = 0;
  for (long long k = (1), kend = (n); k <= kend; ++k)
    for (long long i = (1), iend = (n); i <= iend; ++i)
      for (long long j = (1), jend = (n); j <= jend; ++j)
        dn(dis[i][j], dis[i][k] + dis[k][j]);
  read(c, b, k, h);
  for (long long i = (1), iend = (c); i <= iend; ++i) {
    read(x[i], a[i], f[i]);
    Add(s, i, 1);
  }
  for (long long i = (1), iend = (b); i <= iend; ++i) {
    read(y[i], d[i]);
    Add(c + i, t, 1);
  }
  for (long long i = (1), iend = (c); i <= iend; ++i)
    for (long long j = (1), jend = (b); j <= jend; ++j) {
      if (dis[x[i]][y[j]] <= f[i] && a[i] >= d[j]) Add(i, c + j, 1);
    }
  long long p = dinic();
  wtb(min(p * k, c * h));
  return 0;
}
