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;
std::mt19937 rnd(
    (int)std::chrono::steady_clock::now().time_since_epoch().count());
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
const int MAXN = 150000;
const int MAXLG = 17;
const int MAXPATH = 150000;
const int MAXSNODES = MAXN * (MAXLG + 2);
int n, npath, need;
vector<int> adj[MAXN];
int path[MAXPATH][2];
int par[MAXN], dep[MAXN], sz[MAXN], heavy[MAXN];
int up[MAXN][MAXLG + 1];
int lid[MAXN], rid[MAXN], nid;
vector<int> bylca[MAXN];
void dfsinit(int at) {
  dep[at] = par[at] == -1 ? 0 : dep[par[at]] + 1;
  sz[at] = 1;
  heavy[at] = -1;
  up[at][0] = par[at] == -1 ? at : par[at];
  for (int k = (0); k < (MAXLG); ++k) up[at][k + 1] = up[up[at][k]][k];
  for (int i = (0); i < (((int)(adj[at]).size())); ++i) {
    int to = adj[at][i];
    if (to == par[at]) continue;
    par[to] = at;
    dfsinit(to);
    sz[at] += sz[to];
    if (heavy[at] == -1 || sz[to] > sz[heavy[at]]) heavy[at] = to;
  }
  rid[at] = nid - 1;
}
void dfsid(int at) {
  lid[at] = nid++;
  for (int i = (0); i < (((int)(adj[at]).size())); ++i) {
    int to = adj[at][i];
    if (to == par[at] || to == heavy[at]) continue;
    dfsid(to);
  }
  if (heavy[at] != -1) dfsid(heavy[at]);
  rid[at] = nid - 1;
}
int calcup(int a, int cnt) {
  for (int k = (0); k <= (MAXLG); ++k)
    if (cnt & (1 << k)) a = up[a][k];
  return a;
}
int lca(int a, int b) {
  if (dep[a] < dep[b]) swap(a, b);
  a = calcup(a, dep[a] - dep[b]);
  if (a == b) return a;
  for (int k = MAXLG; k >= 0; --k)
    if (up[a][k] != up[b][k]) a = up[a][k], b = up[b][k];
  return par[a];
}
bool isdesc(int a, int b) { return lid[b] <= lid[a] && rid[a] <= rid[b]; }
long long ans;
int bit[MAXN + 1];
int bget(int idx) {
  ++idx;
  int ret = 0;
  while (idx > 0) {
    ret += bit[idx];
    idx -= idx & -idx;
  }
  return ret;
}
void bmod(int idx, int by) {
  ++idx;
  while (idx <= n) {
    bit[idx] += by;
    idx += idx & -idx;
  }
}
int bget(int lidx, int ridx) { return bget(ridx) - bget(lidx - 1); }
void dfs1(int at) {
  for (int i = (0); i < (2); ++i) {
    for (int _ = (0); _ < (((int)(bylca[at]).size())); ++_) {
      int id = bylca[at][_];
      int to = path[id][i];
      if (dep[to] - dep[at] < need) continue;
      to = calcup(to, dep[to] - dep[at] - need);
      ans += bget(lid[to], rid[to]);
    }
    for (int _ = (0); _ < (((int)(bylca[at]).size())); ++_) {
      int id = bylca[at][_];
      int to = path[id][i];
      bmod(lid[to], +1);
    }
  }
  for (int i = (0); i < (((int)(adj[at]).size())); ++i) {
    int to = adj[at][i];
    if (to == par[at]) continue;
    dfs1(to);
  }
}
struct SNode {
  int l, r, sum;
};
vector<int> byfst[MAXN];
int sndset[MAXN];
SNode snodes[MAXSNODES];
int nsnodes;
int smake() {
  assert(nsnodes < MAXSNODES);
  SNode node;
  node.l = node.r = -1;
  node.sum = 0;
  snodes[nsnodes++] = node;
  return nsnodes - 1;
}
void spull(int x) {
  snodes[x].sum = 0;
  if (snodes[x].l != -1) snodes[x].sum += snodes[snodes[x].l].sum;
  if (snodes[x].r != -1) snodes[x].sum += snodes[snodes[x].r].sum;
}
void smod(int& x, int l, int r, int IDX, int BY) {
  if (x == -1) x = smake();
  if (l == r) {
    snodes[x].sum += BY;
  } else {
    int m = l + (r - l) / 2;
    if (IDX <= m)
      smod(snodes[x].l, l, m, IDX, BY);
    else
      smod(snodes[x].r, m + 1, r, IDX, BY);
    spull(x);
  }
}
int sget(int x, int l, int r, int L, int R) {
  if (x == -1) return 0;
  if (L <= l && r <= R) {
    return snodes[x].sum;
  } else {
    int m = l + (r - l) / 2;
    int ret = 0;
    if (L <= m) ret += sget(snodes[x].l, l, m, L, R);
    if (m + 1 <= R) ret += sget(snodes[x].r, m + 1, r, L, R);
    return ret;
  }
}
void smerge(int& x, int y) {
  if (y == -1)
    return;
  else if (x == -1) {
    x = y;
    return;
  }
  smerge(snodes[x].l, snodes[y].l);
  smerge(snodes[x].r, snodes[y].r);
  spull(x);
}
void calc(int id, int x, int at, int root) {
  int a = path[id][0], b = path[id][1];
  int extra = max(0, need - (dep[at] - dep[root]));
  if (dep[b] - dep[root] >= extra) {
    int to = extra == 0 ? root : calcup(b, dep[b] - dep[root] - extra);
    int cnt = sget(sndset[x], 0, n - 1, lid[to], rid[to]);
    ans += cnt;
  }
}
int merge(int x, int y, int at, int root) {
  if (((int)(byfst[x]).size()) < ((int)(byfst[y]).size())) swap(x, y);
  for (int _ = (0); _ < (((int)(byfst[y]).size())); ++_) {
    int id = byfst[y][_];
    calc(id, x, at, root);
    byfst[x].push_back(id);
  }
  smerge(sndset[x], sndset[y]);
  byfst[y].clear();
  sndset[y] = -1;
  return x;
}
int dfs2(int at, int root) {
  int ret = at;
  for (int _ = (0); _ < (((int)(byfst[at]).size())); ++_) {
    int id = byfst[at][_];
    int a = path[id][0], b = path[id][1];
    calc(id, ret, at, root);
    smod(sndset[ret], 0, n - 1, lid[b], +1);
  }
  for (int i = (0); i < (((int)(adj[at]).size())); ++i) {
    int to = adj[at][i];
    if (to == par[at] || to == heavy[root]) continue;
    int sub = dfs2(to, root);
    ret = merge(ret, sub, at, root);
  }
  return ret;
}
long long solve() {
  par[0] = -1;
  dfsinit(0);
  nid = 0;
  dfsid(0);
  for (int i = (0); i < (n); ++i) bylca[i].clear();
  for (int i = (0); i < (npath); ++i) {
    int &a = path[i][0], &b = path[i][1];
    if (lid[a] > lid[b]) swap(a, b);
    int c = lca(a, b);
    bylca[c].push_back(i);
  }
  ans = 0;
  for (int i = (0); i <= (n); ++i) bit[i] = 0;
  dfs1(0);
  nsnodes = 0;
  for (int i = (0); i < (n); ++i) byfst[i].clear(), sndset[i] = -1;
  for (int at = (0); at < (n); ++at) {
    for (int _ = (0); _ < (((int)(bylca[at]).size())); ++_) {
      int id = bylca[at][_];
      int a = path[id][0], b = path[id][0];
      if (heavy[at] != -1) assert(!isdesc(a, heavy[at]));
      byfst[a].push_back(id);
    }
    int sub = dfs2(at, at);
    assert(((int)(byfst[sub]).size()) == ((int)(bylca[at]).size()));
    nsnodes = 0;
    byfst[sub].clear();
    sndset[sub] = -1;
  }
  return ans;
}
void run() {
  scanf("%d%d%d", &n, &npath, &need);
  for (int i = (0); i < (n - 1); ++i) {
    int a, b;
    scanf("%d%d", &a, &b);
    --a, --b;
    adj[a].push_back(b), adj[b].push_back(a);
  }
  for (int i = (0); i < (npath); ++i)
    for (int j = (0); j < (2); ++j) scanf("%d", &path[i][j]), --path[i][j];
  printf("%lld\n", solve());
}
int main() {
  run();
  return 0;
}
