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 = 0x3f3f3f3f;
const long long INF = 0x3f3f3f3f3f3f3f3fll;
const int maxn = 150005;
int n, m, k;
vector<int> nei[maxn], qry[maxn], egs[maxn], nd;
int siz[maxn], fa[19][maxn], dep[maxn], dfn[maxn], tmc;
vector<pair<int, int> > cs[maxn];
vector<pair<pair<int, int>, pair<int, int> > > vs[maxn];
struct Fenwick {
  int dt[maxn];
  void inline add(int a, int x) {
    while (a < maxn) dt[a] += x, a += a & -a;
  }
  int inline sum(int a) {
    int res = 0;
    while (a) res += dt[a], a -= a & -a;
    return res;
  }
  int inline sum(int l, int r) { return sum(r) - sum(l - 1); }
} bit;
void dfs(int now, int lst) {
  dfn[now] = ++tmc;
  siz[now] = 1;
  fa[0][now] = lst;
  dep[now] = dep[lst] + 1;
  for (int i = 1; i <= (18); ++i) fa[i][now] = fa[i - 1][fa[i - 1][now]];
  for (auto &to : (nei[now])) {
    if (to == lst) continue;
    dfs(to, now);
    siz[now] += siz[to];
  }
}
int inline gfa(int a, int up) {
  for (int i = 0; i < (19); ++i)
    if ((up >> i) & 1) a = fa[i][a];
  return a;
}
int inline lca(int a, int b) {
  if (dep[a] < dep[b]) swap(a, b);
  a = gfa(a, dep[a] - dep[b]);
  if (a == b) return a;
  for (int i = (18); (-1) > 0 ? i <= (0) : i >= (0); i += (-1))
    if (fa[i][a] != fa[i][b]) a = fa[i][a], b = fa[i][b];
  return fa[0][a];
}
long long ans = 0;
void inline dfs1(int now, int lst) {
  for (auto &it : (cs[now])) {
    int u = it.first, v = it.second;
    if (dep[u] - dep[now] >= k) {
      int to = gfa(u, dep[u] - dep[now] - k);
      ans += bit.sum(dfn[to], dfn[to] + siz[to] - 1);
    }
    if (dep[v] - dep[now] >= k) {
      int to = gfa(v, dep[v] - dep[now] - k);
      ans += bit.sum(dfn[to], dfn[to] + siz[to] - 1);
    }
    bit.add(dfn[u], 1);
    bit.add(dfn[v], 1);
  }
  for (auto &to : (nei[now]))
    if (to != lst) dfs1(to, now);
  for (auto &it : (cs[now])) {
    int u = it.first, v = it.second;
    bit.add(dfn[u], -1);
    bit.add(dfn[v], -1);
  }
}
void inline gvtree() {
  sort((nd).begin(), (nd).end(), [&](int a, int b) { return dfn[a] < dfn[b]; });
  nd.erase(unique((nd).begin(), (nd).end()), nd.end());
  vector<int> stk;
  stk.push_back(1);
  egs[1].clear();
  for (auto &to : (nd)) {
    int lc = lca(to, stk.back());
    if (lc != stk.back()) {
      while (((int)(stk).size()) > 1 &&
             dfn[lc] < dfn[stk[((int)(stk).size()) - 2]]) {
        egs[stk[((int)(stk).size()) - 2]].push_back(stk.back());
        stk.pop_back();
      }
      if (dfn[lc] != dfn[stk[((int)(stk).size()) - 2]]) {
        egs[lc].clear();
        egs[lc].push_back(stk.back());
        stk.back() = lc;
      } else {
        egs[lc].push_back(stk.back());
      }
    }
    egs[to].clear();
    stk.push_back(to);
  }
  while (((int)(stk).size()) > 1)
    egs[stk[((int)(stk).size()) - 2]].push_back(stk.back()), stk.pop_back();
}
int dt[maxn << 3], ls[maxn << 3], rs[maxn << 3], nds;
int rt[maxn], rts;
vector<int> ts[maxn];
void inline add(int to, int x, int &now, int nl = 1, int nr = n) {
  if (!now) now = ++nds;
  if (nl == nr) return void(dt[now] += x);
  int m = (nl + nr) >> 1;
  if (m >= to)
    add(to, x, ls[now], nl, m);
  else
    add(to, x, rs[now], m + 1, nr);
  dt[now] = dt[ls[now]] + dt[rs[now]];
}
int inline sum(int l, int r, int now, int nl = 1, int nr = n) {
  if (!now || nl > r || nr < l) return 0;
  if (nl >= l && nr <= r) return dt[now];
  int m = (nl + nr) >> 1;
  return sum(l, r, ls[now], nl, m) + sum(l, r, rs[now], m + 1, nr);
}
int inline merge(int l, int r) {
  if (!l || !r) return l + r;
  dt[l] += dt[r];
  ls[l] = merge(ls[l], ls[r]);
  rs[l] = merge(rs[l], rs[r]);
  return l;
}
int inline mrg(int ca, int cb, int now, int lca) {
  if (!ca || !cb) return ca + cb;
  if (((int)(ts[ca]).size()) < ((int)(ts[cb]).size())) swap(ca, cb);
  for (auto &to : (ts[cb])) {
    ts[ca].push_back(to);
    int up =
        gfa(to, min(dep[to] - dep[lca], dep[to] + dep[now] - 2 * dep[lca] - k));
    ans += sum(dfn[up], dfn[up] + siz[up] - 1, rt[ca]);
    if (dep[now] - dep[lca] >= k) ans -= sum(1, n, rt[ca]);
    if (dep[to] - dep[lca] >= k) {
      int up = gfa(to, dep[to] - dep[lca] - k);
      ans -= sum(dfn[up], dfn[up] + siz[up] - 1, rt[ca]);
    }
  }
  rt[ca] = merge(rt[ca], rt[cb]);
  return ca;
}
int inline dfs2(int now, int lca) {
  int cid = 0;
  for (auto &to : (egs[now])) cid = mrg(cid, dfs2(to, lca), now, lca);
  for (auto &id : (qry[now])) {
    rt[++rts] = 0;
    ts[rts].push_back(id);
    add(dfn[id], 1, rt[rts]);
    cid = mrg(cid, rts, now, lca);
  }
  return cid;
}
int main() {
  scanf("%d%d%d", &n, &m, &k);
  for (int i = 1; i <= (n - 1); ++i) {
    int u, v;
    scanf("%d%d", &u, &v);
    nei[u].push_back(v);
    nei[v].push_back(u);
  }
  dfs(1, 0);
  for (int i = 1; i <= (m); ++i) {
    int u, v;
    scanf("%d%d", &u, &v);
    int c = lca(u, v);
    cs[c].emplace_back(u, v);
    if (u != c && v != c) {
      int du = gfa(u, dep[u] - dep[c] - 1), dv = gfa(v, dep[v] - dep[c] - 1);
      if (du > dv) swap(du, dv), swap(u, v);
      vs[c].emplace_back(make_pair(du, dv), make_pair(u, v));
    }
    u = dfn[u];
    v = dfn[v];
    if (u > v) swap(u, v);
  }
  for (int i = 1; i <= (n); ++i) sort((cs[i]).begin(), (cs[i]).end());
  dfs1(1, 0);
  for (int i = 1; i <= (n); ++i)
    for (int j = 0; j < (((int)(vs[i]).size())); ++j) {
      auto &it = vs[i][j];
      nd.clear();
      int nxt;
      for (nxt = j; nxt < ((int)(vs[i]).size()) && vs[i][nxt].first == it.first;
           ++nxt) {
        nd.push_back(vs[i][nxt].second.first);
      }
      gvtree();
      --nxt;
      for (int k = (j); k <= (nxt); ++k) {
        auto it = vs[i][k];
        qry[it.second.first].push_back(it.second.second);
      }
      dfs2(1, i);
      for (int k = (j); k <= (nxt); ++k) {
        auto it = vs[i][k];
        qry[it.second.first].clear();
      }
      j = nxt;
    }
  printf("%lld\n", ans);
  return 0;
}
