#include <bits/stdc++.h>
using namespace std;
const int maxn = 150005;
int n, m, k, in[maxn], dep[maxn], fa[maxn][19], st[maxn], ed[maxn], tim,
    sta[maxn], top;
int rt[maxn], ls[maxn * 40], rs[maxn * 40], sum[maxn * 40][2], sz;
long long ans;
vector<int> g[maxn], gson[maxn];
struct path {
  int x, y, z, a, b;
} e[maxn];
vector<path> h[maxn];
struct chain {
  int x, y, b;
};
vector<chain> w[maxn], t[maxn];
void dfs1(int x, int ff) {
  fa[x][0] = ff, dep[x] = dep[ff] + 1, st[x] = ++tim;
  for (int i = 1; i <= 18; i++) fa[x][i] = fa[fa[x][i - 1]][i - 1];
  for (int i = 0; i < (int)g[x].size(); i++)
    if (g[x][i] != ff) dfs1(g[x][i], x);
  ed[x] = tim;
}
inline void add_path(int x, int y, int &z, int &a, int &b) {
  if (dep[x] < dep[y]) swap(x, y);
  for (int i = 18; i >= 0; i--)
    if (dep[fa[x][i]] > dep[y]) x = fa[x][i];
  if (fa[x][0] == y) {
    z = y, a = x, b = 0;
    return;
  }
  if (dep[x] > dep[y]) x = fa[x][0];
  for (int i = 18; i >= 0; i--)
    if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
  z = fa[x][0], a = x, b = y;
}
inline int LCA(int x, int y) {
  if (dep[x] < dep[y]) swap(x, y);
  for (int i = 18; i >= 0; i--)
    if (dep[fa[x][i]] >= dep[y]) x = fa[x][i];
  if (x == y) return x;
  for (int i = 18; i >= 0; i--)
    if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
  return fa[x][0];
}
void update(int &rt, int l, int r, int u, int v, int z) {
  if (!rt) rt = ++sz, ls[rt] = rs[rt] = sum[rt][0] = sum[rt][1] = 0;
  sum[rt][z] += v;
  if (l == r) return;
  int mid = (l + r) >> 1;
  if (u <= mid)
    update(ls[rt], l, mid, u, v, z);
  else
    update(rs[rt], mid + 1, r, u, v, z);
}
int query(int rt, int l, int r, int x, int y, int z) {
  if (!rt) return 0;
  if (x <= l && r <= y) return sum[rt][z];
  int mid = (l + r) >> 1, ans = 0;
  if (x <= mid) ans += query(ls[rt], l, mid, x, y, z);
  if (y > mid) ans += query(rs[rt], mid + 1, r, x, y, z);
  return ans;
}
int merge(int x, int y) {
  if (!x || !y) return x | y;
  sum[x][0] += sum[y][0];
  sum[x][1] += sum[y][1];
  ls[x] = merge(ls[x], ls[y]);
  rs[x] = merge(rs[x], rs[y]);
  return x;
}
inline int jump(int x, int k) {
  k = dep[x] - k;
  for (int i = 18; i >= 0; i--)
    if (dep[fa[x][i]] >= k) x = fa[x][i];
  return x;
}
inline void calc(int x, int k, int rt) {
  if (k < 0) return;
  int a = jump(x, k);
  ans += query(rt, 1, n, st[a], ed[a], 0);
}
void dfs2(int x) {
  for (int i = 0, y; i < (int)g[x].size(); i++)
    if (g[x][i] != fa[x][0]) y = g[x][i], dfs2(y), rt[x] = merge(rt[x], rt[y]);
  vector<path>::iterator it;
  for (it = h[x].begin(); it != h[x].end(); it++) {
    update(rt[x], 1, n, st[it->x], -1, 0);
    if (it->y != x) update(rt[x], 1, n, st[it->y], -1, 0);
  }
  for (it = h[x].begin(); it != h[x].end(); it++) {
    calc(it->x, dep[it->x] - dep[x] - k, rt[x]);
    if (it->y > 0) calc(it->y, dep[it->y] - dep[x] - k, rt[x]);
  }
  if (in[x]) update(rt[x], 1, n, st[x], in[x], 0);
}
void dfs3(int x, int anc) {
  vector<chain>::iterator it;
  if (dep[x] - dep[anc] >= k) {
    ans += (long long)t[x].size() * ((long long)t[x].size() - 1) / 2;
    int sz = 0;
    for (it = t[x].begin(); it != t[x].end(); it++) {
      update(rt[x], 1, n, st[it->y], 1, 0);
      ans += sz - (it->b ? query(rt[x], 1, n, it->b, it->b, 1) : 0);
      if (it->b) update(rt[x], 1, n, it->b, 1, 1);
      sz++;
    }
  } else {
    for (it = t[x].begin(); it != t[x].end(); it++)
      calc(it->y, dep[it->y] - dep[anc] - (k - (dep[x] - dep[anc])), rt[x]),
          update(rt[x], 1, n, st[it->y], 1, 0);
  }
  for (int i = 0; i < (int)gson[x].size(); i++) {
    int y = gson[x][i];
    dfs3(y, anc);
    if ((int)t[x].size() < (int)t[y].size())
      swap(t[x], t[y]), swap(rt[x], rt[y]);
    if (dep[x] - dep[anc] >= k) {
      ans += (long long)t[x].size() * (long long)t[y].size();
      for (it = t[y].begin(); it != t[y].end(); it++)
        ans += ((long long)t[x].size() -
                (it->b ? query(rt[x], 1, n, it->b, it->b, 1) : 0));
    } else {
      for (it = t[y].begin(); it != t[y].end(); it++)
        calc(it->y, dep[it->y] - dep[anc] - (k - (dep[x] - dep[anc])), rt[x]);
    }
    rt[x] = merge(rt[x], rt[y]);
    for (it = t[y].begin(); it != t[y].end(); it++) t[x].push_back(*it);
    rt[y] = 0;
    vector<chain>().swap(t[y]);
  }
  vector<int>().swap(gson[x]);
}
inline bool cmp(const int &x, const int &y) { return st[x] < st[y]; }
inline void solve(int x, int anc) {
  if ((int)w[x].size() <= 1) return;
  sta[top = 1] = x;
  vector<chain>::iterator it;
  static int q[maxn];
  int tot = 0;
  for (it = w[x].begin(); it != w[x].end(); it++) q[++tot] = it->x;
  sort(q + 1, q + tot + 1, cmp);
  for (int i = 1; i <= tot; i++) {
    int lca = LCA(sta[top], q[i]);
    while (dep[lca] < dep[sta[top]]) {
      if (dep[sta[top - 1]] <= dep[lca]) {
        gson[lca].push_back(sta[top]), top--;
        if (sta[top] != lca) sta[++top] = lca;
        break;
      }
      gson[sta[top - 1]].push_back(sta[top]), top--;
    }
    if (sta[top] != q[i]) sta[++top] = q[i];
  }
  while (--top) gson[sta[top]].push_back(sta[top + 1]);
  for (it = w[x].begin(); it != w[x].end(); it++) t[it->x].push_back(*it);
  sz = 0, dfs3(x, anc), rt[x] = 0;
  vector<chain>().swap(t[x]);
}
int main() {
  scanf("%d%d%d", &n, &m, &k);
  int x, y;
  for (int i = 1; i < n; i++) {
    scanf("%d%d", &x, &y);
    g[x].push_back(y);
    g[y].push_back(x);
  }
  for (int i = 1; i <= n; i++) sort(g[i].begin(), g[i].end());
  dfs1(1, 0);
  for (int i = 1; i <= m; i++) {
    scanf("%d%d", &e[i].x, &e[i].y);
    if (dep[e[i].x] < dep[e[i].y]) swap(e[i].x, e[i].y);
    add_path(e[i].x, e[i].y, e[i].z, e[i].a, e[i].b);
    in[e[i].x]++;
    if (e[i].y != e[i].z) in[e[i].y]++;
    h[e[i].z].push_back(e[i]);
  }
  dfs2(1), ans *= 2;
  for (int i = 1; i <= n; i++) rt[i] = 0;
  for (int i = 1; i <= n; i++) {
    for (vector<path>::iterator it = h[i].begin(); it != h[i].end(); it++) {
      if (!it->b)
        w[it->a].push_back((chain){it->x, it->y, 0});
      else
        w[it->a].push_back((chain){it->x, it->y, it->b}),
            w[it->b].push_back((chain){it->y, it->x, it->a});
    }
    for (int j = 0; j < (int)g[i].size(); j++)
      if (g[i][j] != fa[i][0]) solve(g[i][j], i);
  }
  printf("%lld\n", ans / 2);
  return 0;
}
