30 30 10
6 1
8 27
5 1
21 6
24 15
12 5
29 7
22 7
23 17
2 13
23 11
29 6
14 18
29 16
27 25
15 2
27 4
19 30
28 19
17 2
27 16
3 4
9 25
19 16
10 16
18 17
26 11
2 27
16 20
13 23
1 4
27 7
6 20
17 30
1 18
2 17
1 11
5 9
25 13
11 20
14 25
30 21
6 24
12 2
25 12
22 13
10 27
24 29
19 24
28 29
24 23
9 6
12 15
11 15
23 14
12 28
28 25
2 11
19 30
 2 2 1
1 2
2 1
1 2

0 1
#include <bits/stdc++.h>
using namespace std;
const int inf = (int)1.01e9;
const long long infll = (long long)1.01e18;
const long double eps = 1e-9;
const long double pi = acos((long double)-1);
mt19937 mrand(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int x) { return mrand() % x; }
void precalc() {}
const int maxn = (int)1.5e5 + 5;
int n, m, k;
vector<int> g[maxn];
pair<int, int> ps[maxn];
bool read() {
  if (scanf("%d%d%d", &n, &m, &k) < 3) {
    return false;
  }
  for (int i = 0; i < n; i++) {
    g[i].clear();
  }
  for (int i = 0; i < n - 1; i++) {
    int v, u;
    scanf("%d%d", &v, &u);
    v--;
    u--;
    g[v].push_back(u);
    g[u].push_back(v);
  }
  for (int i = 0; i < m; i++) {
    scanf("%d%d", &ps[i].first, &ps[i].second);
    ps[i].first--;
    ps[i].second--;
  }
  return true;
}
const int logn = 18;
int p[maxn][logn];
int path[maxn];
int tin[maxn], tout[maxn], t;
int dep[maxn];
void dfs0(int v, int pr) {
  path[t] = v;
  tin[v] = t++;
  p[v][0] = (pr == -1 ? v : pr);
  dep[v] = (pr == -1 ? 0 : dep[pr] + 1);
  for (int i = 1; i < logn; i++) {
    p[v][i] = p[p[v][i - 1]][i - 1];
  }
  for (int i = 0; i < ((int)(g[v]).size()); i++) {
    int u = g[v][i];
    if (u == pr) {
      continue;
    }
    dfs0(u, v);
  }
  tout[v] = t;
}
bool anc(int v, int u) { return tin[v] <= tin[u] && tout[u] <= tout[v]; }
int getLca(int v, int u) {
  if (anc(v, u)) {
    return v;
  }
  if (anc(u, v)) {
    return u;
  }
  for (int i = logn - 1; i >= 0; i--) {
    if (!anc(p[v][i], u)) {
      v = p[v][i];
    }
  }
  return p[v][0];
}
int goUp(int v, int k) {
  for (int i = 0; i < logn; i++) {
    if (k & (1 << i)) {
      v = p[v][i];
    }
  }
  return v;
}
struct node {
  int x, y, ts;
  node *l, *r;
  node(int xx) : x(xx), y(mrand()), ts(1), l(0), r(0) {}
  node *update() {
    ts = 1 + (l ? l->ts : 0) + (r ? r->ts : 0);
    return this;
  }
};
int tsz(node *v) { return (v ? v->ts : 0); }
node *merge(node *l, node *r) {
  if (!l) {
    return r;
  }
  if (!r) {
    return l;
  }
  if (l->y < r->y) {
    l->r = merge(l->r, r);
    return l->update();
  } else {
    r->l = merge(l, r->l);
    return r->update();
  }
}
void split(node *v, int x, node *&l, node *&r) {
  if (!v) {
    l = 0;
    r = 0;
    return;
  }
  if (v->x < x) {
    split(v->r, x, v->r, r);
    l = v->update();
  } else {
    split(v->l, x, l, v->l);
    r = v->update();
  }
}
vector<int> qs[maxn];
long long res;
vector<int> vs;
void getVs(node *v) {
  if (!v) {
    return;
  }
  getVs(v->l);
  vs.push_back(path[v->x]);
  getVs(v->r);
}
void delV(node *&rt, int v) {
  node *l, *m, *r;
  split(rt, tin[v], l, r);
  split(r, tout[v], m, r);
  rt = merge(l, r);
}
int getCnt(node *&rt, int v) {
  node *l, *m, *r;
  split(rt, tin[v], l, r);
  split(r, tout[v], m, r);
  int res = tsz(m);
  rt = merge(l, merge(m, r));
  return res;
}
void updateRes(node *&rt, int v, int u) {
  int w = getLca(v, u);
  int a = dep[v] - dep[w], b = dep[u] - dep[w];
  if (a + b < k) {
    return;
  }
  if (a < k) {
    if (tin[v] > tin[u]) {
      return;
    }
    int x = goUp(u, a + b - k);
    res += getCnt(rt, x);
    return;
  }
  {
    int x = goUp(v, k - 1);
    res += tsz(rt) - getCnt(rt, x);
  }
  if (tin[v] > tin[u] && w != u) {
    int x = goUp(u, b - 1);
    res -= getCnt(rt, x);
  }
}
void addVer(node *&rt, int v) {
  node *l, *r;
  split(rt, tin[v], l, r);
  rt = merge(merge(l, new node(tin[v])), r);
}
node *dfs(int v, int pr) {
  node *vrt = 0;
  for (int i = 0; i < ((int)(g[v]).size()); i++) {
    int u = g[v][i];
    if (u == pr) {
      continue;
    }
    node *urt = dfs(u, v);
    delV(urt, v);
    if (tsz(vrt) < tsz(urt)) {
      swap(vrt, urt);
    }
    vs.clear();
    getVs(urt);
    for (int it = 0; it < ((int)(vs).size()); it++) {
      updateRes(vrt, v, vs[it]);
    }
    for (int it = 0; it < ((int)(vs).size()); it++) {
      addVer(vrt, vs[it]);
    }
  }
  for (int i = 0; i < ((int)(qs[v]).size()); i++) {
    updateRes(vrt, v, qs[v][i]);
    addVer(vrt, qs[v][i]);
  }
  return vrt;
}
void solve() {
  t = 0;
  dfs0(0, -1);
  for (int i = 0; i < n; i++) {
    qs[i].clear();
  }
  for (int i = 0; i < m; i++) {
    int v = ps[i].first, u = ps[i].second;
    if (anc(u, v)) {
      swap(v, u);
    }
    if (!anc(v, u)) {
      qs[v].push_back(u);
    }
    qs[u].push_back(v);
  }
  res = 0;
  dfs(0, -1);
  printf("%lld\n", res);
}
int main() {
  precalc();
  while (read()) {
    solve();
  }
  return 0;
}
