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;
template <class T>
istream &operator>>(istream &is, vector<T> &v) {
  for (T &x : v) is >> x;
  return is;
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  if (!v.empty()) {
    os << v.front();
    for (int i = 1; i < v.size(); ++i) os << ' ' << v[i];
  }
  return os;
}
const int N = 150010;
int n, m, k;
int dfn[N], tab[N], sub[N], pref[N], dep[N], prt[N], top[N];
int s[N], t[N];
struct FW {
  int fw[N];
  void add(int k, int x) {
    for (; k <= n; k += k & -k) fw[k] += x;
  }
  int query(int k) const {
    int ret = 0;
    for (; k; k &= k - 1) ret += fw[k];
    return ret;
  }
} fw1, fwa[18];
vector<int> g[N], hang[N];
void dfs(int u) {
  sub[u] = 1;
  for (int v : g[u])
    if (!sub[v]) {
      prt[v] = u;
      dep[v] = dep[u] + 1;
      dfs(v);
      sub[u] += sub[v];
      if (sub[pref[u]] < sub[v]) pref[u] = v;
    }
}
void hld(int u) {
  static int t;
  dfn[u] = ++t;
  tab[t] = u;
  if (!top[u]) top[u] = u;
  if (pref[u]) {
    top[pref[u]] = top[u];
    hld(pref[u]);
    for (int v : g[u])
      if (!dfn[v]) hld(v);
  }
}
int lca(int u, int v) {
  int x = top[u], y = top[v];
  while (x != y) {
    if (dep[x] > dep[y]) {
      swap(x, y);
      swap(u, v);
    }
    v = prt[y];
    y = top[v];
  }
  return dep[u] < dep[v] ? u : v;
}
int la(int u, int k) {
  int x = top[u];
  while (dep[u] - dep[x] < k) {
    k -= dep[u] - dep[x] + 1;
    u = prt[x];
    x = top[u];
  }
  return tab[dfn[u] - k];
}
int query(const FW &fwt, int u) {
  return fwt.query(dfn[u] + sub[u] - 1) - fwt.query(dfn[u] - 1);
}
long long ans;
vector<pair<int, int>> subs[N];
void dfs2(int u) {
  for (int i : hang[u]) {
    fw1.add(dfn[s[i]], 1);
    fw1.add(dfn[t[i]], 1);
  }
  for (int v : g[u])
    if (prt[v] == u) dfs2(v);
  for (int i : hang[u]) {
    if (s[i] != u && t[i] != u) {
      subs[la(s[i], dep[s[i]] - dep[u] - 1)].emplace_back(s[i], t[i]);
      subs[la(t[i], dep[t[i]] - dep[u] - 1)].emplace_back(t[i], s[i]);
    }
    fw1.add(dfn[s[i]], -1);
    fw1.add(dfn[t[i]], -1);
    if (dep[s[i]] - dep[u] >= k)
      ans += query(fw1, la(s[i], dep[s[i]] - dep[u] - k)) * 2;
    if (dep[t[i]] - dep[u] >= k)
      ans += query(fw1, la(t[i], dep[t[i]] - dep[u] - k)) * 2;
  }
}
int relabel[N], vsub[N], vprt[N], vtop[N], vpref[N];
vector<int> vg[N], vhang[N];
bool isp(int u, int v) { return dfn[u] <= dfn[v] && dfn[u] + sub[u] > dfn[v]; }
void solve(int u) {
  vector<int> vers;
  vers.push_back(u);
  for (auto [x, ig] : subs[u]) vers.push_back(x);
  sort(vers.begin(), vers.end(), [&](int x, int y) { return dfn[x] < dfn[y]; });
  vector<int> tmp;
  tmp.push_back(vers.front());
  for (int i = 1; i < vers.size(); ++i) {
    tmp.push_back(lca(vers[i - 1], vers[i]));
    tmp.push_back(vers[i]);
  }
  sort(tmp.begin(), tmp.end(), [&](int x, int y) { return dfn[x] < dfn[y]; });
  tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end());
  int r = tmp.size();
  for (int i = 0; i < r; ++i) relabel[tmp[i]] = i;
  vector<int> stk;
  for (int x : tmp) {
    while (!stk.empty() && !isp(stk.back(), x)) stk.pop_back();
    if (!stk.empty()) {
      vg[relabel[x]].push_back(relabel[stk.back()]);
      vg[relabel[stk.back()]].push_back(relabel[x]);
    }
    stk.push_back(x);
  }
  fill(vsub, vsub + r, 0);
  fill(vpref, vpref + r, -1);
  function<void(int)> dfs = [&](int x) {
    vsub[x] = 1;
    for (int y : vg[x])
      if (!vsub[y]) {
        vprt[y] = x;
        dfs(y);
        vsub[x] += vsub[y];
        if (vpref[x] == -1 || vsub[vpref[x]] < vsub[y]) vpref[x] = y;
      }
  };
  dfs(0);
  for (auto [v, w] : subs[u]) vhang[relabel[v]].push_back(w);
  fill(vtop, vtop + r, -1);
  vector<int> trav;
  function<void(int, int)> hld = [&](int x, int adep) {
    if (vtop[x] == -1) vtop[x] = x;
    if (vpref[x] != -1) {
      vtop[vpref[x]] = vtop[x];
      hld(vpref[x], adep);
    }
    for (int y : vg[x]) {
      if (vtop[y] == -1) {
        int j = trav.size();
        hld(y, adep + 1);
        while (j < trav.size()) fwa[adep + 1].add(dfn[trav[j++]], -1);
      }
    }
    for (int y : vhang[x]) {
      int cur = x;
      for (int j = adep; j >= 0; --j, cur = vprt[vtop[cur]]) {
        int dst = dep[tmp[cur]] - dep[prt[u]];
        if (dst < k && dep[y] - dep[prt[u]] >= k - dst) {
          ans += query(fwa[j], la(y, dep[y] - dep[prt[u]] - k + dst));
          if (dep[y] - dep[prt[u]] >= k)
            ans -= query(fwa[j], la(y, dep[y] - dep[prt[u]] - k));
        }
        if (dst >= k && dep[y] - dep[prt[u]] >= k) {
          ans -= query(fwa[j], la(y, dep[y] - dep[prt[u]] - k));
        }
        fwa[j].add(dfn[y], 1);
      }
      trav.push_back(y);
    }
  };
  hld(0, 0);
  for (int v : trav) {
    fwa[0].add(dfn[v], -1);
  }
  for (int i = 0; i < tmp.size(); ++i) {
    vg[i].clear();
    vhang[i].clear();
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cin >> n >> m >> k;
  for (int rep = 1; rep < n; ++rep) {
    int u, v;
    cin >> u >> v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  int rt = 1;
  dfs(rt);
  hld(rt);
  for (int i = 1; i <= m; ++i) cin >> s[i] >> t[i];
  for (int i = 1; i <= m; ++i) hang[lca(s[i], t[i])].push_back(i);
  dfs2(rt);
  for (int u = 1; u <= n; ++u)
    if (!subs[u].empty()) solve(u);
  cout << (ans / 2) << '\n';
  return 0;
}
