#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 150000 + 23;
int n, m, k, fa[MAXN][18], depth[MAXN], dfn[MAXN], siz[MAXN], cnt = 0;
vector<int> g[MAXN];
long long rest = 0;
void dfs(int now, int pre) {
  fa[now][0] = pre;
  dfn[now] = ++cnt;
  siz[now] = 1;
  for (int i = 1; i <= 17; ++i) fa[now][i] = fa[fa[now][i - 1]][i - 1];
  for (auto it : g[now])
    if (it != pre)
      depth[it] = depth[now] + 1, dfs(it, now), siz[now] += siz[it];
}
int jump(int now, int dis) {
  for (int i = 0; i < 18; ++i)
    if ((dis >> i) & 1) now = fa[now][i];
  return now;
}
int lca(int u, int v) {
  if (depth[u] > depth[v]) swap(u, v);
  v = jump(v, depth[v] - depth[u]);
  if (u == v) return u;
  for (int i = 17; i >= 0; --i) {
    if (fa[u][i] != fa[v][i]) {
      u = fa[u][i], v = fa[v][i];
    }
  }
  return fa[u][0];
}
struct BIT {
  int bit[MAXN];
  BIT() { memset(bit, 0, sizeof(bit)); }
  void add(int pos, int val) {
    while (pos <= n) {
      bit[pos] += val, pos += pos & (-pos);
    }
  }
  int sum(int pos) {
    int s = 0;
    while (pos) {
      s += bit[pos], pos ^= pos & (-pos);
    }
    return s;
  }
  int query(int l, int r) {
    if (r < l) return 0;
    return sum(r) - sum(l - 1);
  }
} ds1, ds2;
vector<pair<int, int> > v[MAXN];
void work3(vector<int>& V, int now) {
  for (auto it : V) {
    if (depth[it] - depth[now] >= k) {
      int z = jump(it, depth[it] - depth[now] - k);
      rest -= ds2.query(dfn[z], dfn[z] + siz[z] - 1);
    }
    ds2.add(dfn[it], 1);
  }
  for (auto it : V) ds2.add(dfn[it], -1);
}
vector<int> vt[MAXN];
bool cmp(int A, int B) { return dfn[A] < dfn[B]; }
vector<pair<int, int> > va[MAXN];
int root[MAXN];
vector<pair<int, int> > inf[MAXN];
struct node {
  int sum, l, r;
  node() { sum = l = r = 0; }
};
node dt[MAXN * 23];
int newnode() {
  dt[++cnt] = node();
  return cnt;
}
void pu(int now) { dt[now].sum = dt[dt[now].l].sum + dt[dt[now].r].sum; }
const int N = 1 << 18;
void add(int pos, int now, int l = 1, int r = N + 1) {
  if (l == r - 1) {
    dt[now].sum++;
    return;
  }
  int mid = (l + r) >> 1;
  if (mid > pos) {
    if (!dt[now].l) dt[now].l = newnode();
    add(pos, dt[now].l, l, mid);
  } else {
    if (!dt[now].r) dt[now].r = newnode();
    add(pos, dt[now].r, mid, r);
  }
  pu(now);
}
int query(int a, int b, int now, int l = 1, int r = N + 1) {
  if (!now) return 0;
  if (r <= a || l >= b) return 0;
  if (r <= b && l >= a) return dt[now].sum;
  int mid = (l + r) >> 1;
  return query(a, b, dt[now].l, l, mid) + query(a, b, dt[now].r, mid, r);
}
int merge(int a, int b) {
  if (!a || !b) return a + b;
  dt[a].sum += dt[b].sum;
  dt[a].l = merge(dt[a].l, dt[b].l);
  dt[a].r = merge(dt[a].r, dt[b].r);
  return a;
}
void gao(int now, int t, int rt, int T) {
  t = max(0, k - t);
  if (depth[now] - depth[rt] >= t) {
    now = jump(now, depth[now] - depth[rt] - t);
    rest += query(dfn[now], dfn[now] + siz[now], T);
  }
}
void Run(int now, int s) {
  for (auto it : inf[now]) {
    gao(it.second, depth[now] - depth[s], s, root[now]);
    va[now].push_back(it);
    add(dfn[it.second], root[now]);
  }
  for (auto it : vt[now]) {
    Run(it, s);
    if (va[it].size() > va[now].size())
      swap(va[it], va[now]), swap(root[now], root[it]);
    for (auto itt : va[it]) {
      gao(itt.second, depth[now] - depth[s], s, root[now]);
      va[now].push_back(itt);
    }
    root[now] = merge(root[it], root[now]);
  }
}
void work2(vector<pair<int, int> >& V, int now) {
  if (V.empty()) return;
  vector<int> Lp, Rp;
  for (auto it : V) Lp.push_back(it.first);
  for (auto it : V) Rp.push_back(it.second);
  work3(Lp, now);
  work3(Rp, now);
  vector<int> No;
  for (auto it : V) No.push_back(it.first), No.push_back(it.second);
  sort(No.begin(), No.end(), cmp);
  vector<int> vitt = No;
  for (int i = 0; i < No.size() - 1; ++i) vitt.push_back(lca(No[i], No[i + 1]));
  sort(vitt.begin(), vitt.end());
  vitt.erase(unique(vitt.begin(), vitt.end()), vitt.end());
  cnt = 0;
  for (auto it : vitt) vt[it].clear();
  for (auto it : vitt) va[it].clear(), root[it] = newnode(), inf[it].clear();
  for (auto it : V) inf[it.first].push_back(it);
  sort(vitt.begin(), vitt.end(), cmp);
  stack<int> sta;
  sta.push(vitt[0]);
  for (int i = 1; i <= vitt.size() - 1; ++i) {
    while (dfn[sta.top()] + siz[sta.top()] - 1 < dfn[vitt[i]] ||
           dfn[sta.top()] > dfn[vitt[i]])
      sta.pop();
    vt[sta.top()].push_back(vitt[i]);
    sta.push(vitt[i]);
  }
  Run(vitt[0], now);
}
void work(int now) {
  map<pair<int, int>, vector<pair<int, int> > > M;
  for (auto it : v[now]) {
    if (it.first != now && it.second != now) {
      pair<int, int> A, B;
      A = make_pair(jump(it.first, depth[it.first] - depth[now] - 1),
                    jump(it.second, depth[it.second] - depth[now] - 1));
      B = make_pair(it.first, it.second);
      if (dfn[A.first] > dfn[A.second])
        swap(A.first, A.second), swap(B.first, B.second);
      M[A].push_back(B);
    }
  }
  for (auto ite = M.begin(); ite != M.end(); ++ite) work2(ite->second, now);
}
void gao(int now, int pre) {
  for (auto it : v[now]) {
    int z;
    if (depth[it.second] - depth[now] >= k) {
      z = jump(it.second, depth[it.second] - depth[now] - k);
      rest += ds1.query(dfn[z], dfn[z] + siz[z] - 1);
    }
    if (depth[it.first] - depth[now] >= k) {
      z = jump(it.first, depth[it.first] - depth[now] - k);
      rest += ds1.query(dfn[z], dfn[z] + siz[z] - 1);
    }
    ds1.add(dfn[it.first], 1), ds1.add(dfn[it.second], 1);
  }
  work(now);
  for (auto it : g[now])
    if (it != pre) gao(it, now);
  for (auto it : v[now])
    ds1.add(dfn[it.first], -1), ds1.add(dfn[it.second], -1);
}
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);
    g[u].push_back(v);
    g[v].push_back(u);
  }
  dfs(1, 0);
  for (int i = 1; i <= m; ++i) {
    int s, t;
    scanf("%d%d", &s, &t);
    v[lca(s, t)].push_back(make_pair(s, t));
  }
  gao(1, 0);
  cout << rest << endl;
  return 0;
}
