#include <bits/stdc++.h>
using namespace std;
template <typename T, size_t size>
ostream &operator<<(ostream &os, const array<T, size> &arr) {
  os << '{';
  string sep;
  for (const auto &x : arr) os << sep << x, sep = ", ";
  return os << '}';
}
template <class T>
ostream &operator<<(ostream &os, vector<T> V) {
  os << "[ ";
  for (auto v : V) os << v << " ";
  return os << "]";
}
template <class T>
ostream &operator<<(ostream &os, set<T> S) {
  os << "{ ";
  for (auto s : S) os << s << " ";
  return os << "}";
}
template <class L, class R>
ostream &operator<<(ostream &os, pair<L, R> P) {
  return os << "(" << P.first << "," << P.second << ")";
}
template <class L, class R>
ostream &operator<<(ostream &os, map<L, R> M) {
  os << "{ ";
  for (auto m : M) os << "(" << m.first << ":" << m.second << ") ";
  return os << "}";
}
const int MAX = 1000010;
const int MOD2 = 998244353;
const int MOD1 = 1000000007;
const int INF = 0x3f;
const long long int LLINF = 0x3f3f3f3f3f3f3f3fll;
const long double EPS = 1e-7;
struct edge {
  int from, to, cap, flow, index;
  edge(int from_, int to_, int cap_, int flow_, int index_)
      : from(from_), to(to_), cap(cap_), flow(flow_), index(index_) {}
};
struct PushRelabel {
  int n;
  vector<vector<edge>> g;
  vector<long long> excess;
  vector<int> height, active, count;
  queue<int> Q;
  PushRelabel(int n_)
      : n(n_), g(n_), excess(n_), height(n_), active(n_), count(2 * n_) {}
  void addEdge(int from, int to, int cap) {
    g[from].push_back(edge(from, to, cap, 0, static_cast<int>(g[to].size())));
    if (from == to) g[from].back().index++;
    g[to].push_back(edge(to, from, 0, 0, static_cast<int>(g[from].size()) - 1));
  }
  void enqueue(int v) {
    if (!active[v] and excess[v] > 0) {
      active[v] = true;
      Q.push(v);
    }
  }
  void push(edge &e) {
    int amt = (int)min(excess[e.from], (long long)e.cap - e.flow);
    if (height[e.from] <= height[e.to] or amt == 0) return;
    e.flow += amt;
    g[e.to][e.index].flow -= amt;
    excess[e.to] += amt;
    excess[e.from] -= amt;
    enqueue(e.to);
  }
  void relabel(int v) {
    count[height[v]]--;
    int d = 2 * n;
    for (auto &it : g[v]) {
      if (it.cap - it.flow > 0) d = min(d, height[it.to] + 1);
    }
    height[v] = d;
    count[height[v]]++;
    enqueue(v);
  }
  void gap(int k) {
    for (int v = 0; v < n; v++) {
      if (height[v] < k) continue;
      count[height[v]]--;
      height[v] = max(height[v], n + 1);
      count[height[v]]++;
      enqueue(v);
    }
  }
  void discharge(int v) {
    for (int i = 0; excess[v] > 0 and i < static_cast<int>(g[v].size()); i++)
      push(g[v][i]);
    if (excess[v] > 0) {
      if (count[height[v]] == 1)
        gap(height[v]);
      else
        relabel(v);
    }
  }
  long long max_flow(int source, int dest) {
    count[0] = n - 1;
    count[n] = 1;
    height[source] = n;
    active[source] = active[dest] = 1;
    for (auto &it : g[source]) {
      excess[source] += it.cap;
      push(it);
    }
    while (!Q.empty()) {
      int v = Q.front();
      Q.pop();
      active[v] = false;
      discharge(v);
    }
    long long max_flow = 0;
    for (auto &e : g[source]) max_flow += e.flow;
    return max_flow;
  }
} flow(2005);
const int mxn = 1005;
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  cout << fixed << setprecision(25);
  cerr << fixed << setprecision(10);
  int n, m, s, b, k, h;
  vector<int> x(mxn), a(mxn), f(mxn), y(mxn), d(mxn);
  vector<vector<pair<int, int>>> in(mxn);
  vector<vector<int>> out(mxn), dist(mxn, vector<int>(mxn));
  cin >> n >> m;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++)
      if (i ^ j) dist[i][j] = MOD1;
  for (int i = 1; i <= m; i++) {
    int u, v;
    cin >> u >> v;
    dist[u][v] = dist[v][u] = 1;
  }
  cin >> s >> b >> k >> h;
  for (int i = 1; i <= s; i++) {
    flow.addEdge(0, i, 1);
    cin >> x[i] >> a[i] >> f[i];
  }
  for (int i = 1; i <= b; i++) {
    flow.addEdge(i + 1000, 2004, 1);
    cin >> y[i] >> d[i];
  }
  for (int z = 1; z <= n; z++)
    for (int i = 1; i <= n; i++)
      for (int j = 1; j <= n; j++)
        dist[i][j] = min(dist[i][j], dist[i][z] + dist[z][j]);
  for (int i = 1; i <= s; i++)
    for (int j = 1; j <= b; j++)
      if (dist[x[i]][y[j]] <= f[i] and a[i] >= d[j])
        flow.addEdge(i, 1000 + j, 1);
  cout << min(k * flow.max_flow(0, 2004), s * 1ll * h) << "\n";
}
