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;
int read() {
  int x = 0;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar())
    ;
  for (; isdigit(ch); ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);
  return x;
}
int n, m, k;
long long ans;
struct Edge {
  int to, nxt;
} edge[300010];
int cnt = 1, last[150010];
inline void addedge(int x, int y) {
  edge[++cnt] = (Edge){y, last[x]}, last[x] = cnt;
  edge[++cnt] = (Edge){x, last[y]}, last[y] = cnt;
}
struct Rec {
  int u, v;
} rec[150010];
int gnd[150010][18], dep[150010], siz[150010];
int id[150010], idtot;
void dfs0(int cur, int d) {
  id[cur] = ++idtot;
  dep[cur] = d;
  siz[cur] = 1;
  for (int i = 1; i < 18 && gnd[cur][i - 1]; i++)
    gnd[cur][i] = gnd[gnd[cur][i - 1]][i - 1];
  for (int i = last[cur], v; i; i = edge[i].nxt)
    if ((v = edge[i].to) ^ gnd[cur][0]) {
      gnd[v][0] = cur;
      dfs0(v, d + 1);
      siz[cur] += siz[v];
    }
}
int lift(int x, int t) {
  for (int i = 0; i < 18; i++)
    if (t >> i & 1) x = gnd[x][i];
  return x;
}
int getlca(int x, int y) {
  if (dep[x] < dep[y]) swap(x, y);
  int t = dep[x] - dep[y];
  for (int i = 0; i < 18; i++)
    if (t >> i & 1) x = gnd[x][i];
  if (x == y) return x;
  for (int i = 17; i >= 0; i--)
    if (gnd[x][i] ^ gnd[y][i]) x = gnd[x][i], y = gnd[y][i];
  return gnd[x][0];
}
vector<int> qry[150010];
int tri[150010], bvrn[150010], btim;
void add(int x, int v) {
  for (; x <= n; x += x & -x) {
    if (bvrn[x] ^ btim) bvrn[x] = btim, tri[x] = 0;
    tri[x] += v;
  }
}
int ask(int x) {
  int res = 0;
  for (; x; x -= x & -x)
    if (bvrn[x] == btim) res += tri[x];
  return res;
}
void dfs1(int cur) {
  for (int i = last[cur], v; i; i = edge[i].nxt)
    if ((v = edge[i].to) ^ gnd[cur][0]) dfs1(v);
  for (int i = 0; i < qry[cur].size(); i++) {
    int u = rec[qry[cur][i]].u, v = rec[qry[cur][i]].v;
    ans += ask(id[u]) + ask(id[v]);
  }
  for (int i = 0; i < qry[cur].size(); i++) {
    int u = rec[qry[cur][i]].u, v = rec[qry[cur][i]].v;
    if (dep[u] - dep[cur] >= k) {
      u = lift(u, dep[u] - dep[cur] - k);
      add(id[u], 1);
      add(id[u] + siz[u], -1);
    }
    if (dep[v] - dep[cur] >= k) {
      v = lift(v, dep[v] - dep[cur] - k);
      add(id[v], 1);
      add(id[v] + siz[v], -1);
    }
  }
}
namespace V {
struct Edge {
  int to, nxt;
} edge[150010];
int cnt, last[150010];
inline void addedge(int x, int y) {
  edge[++cnt] = (Edge){y, last[x]}, last[x] = cnt;
}
int stk[150010], stktop, bin[150010], bintop;
int vvrn[150010], vtim;
void push(int x) {
  if (vvrn[x] ^ vtim) vvrn[x] = vtim, stk[++stktop] = x;
}
bool cmp(int x, int y) { return id[x] < id[y]; }
void build() {
  sort(stk + 1, stk + stktop + 1, cmp);
  for (int i = 1, t = stktop, v; i < t; i++)
    if (vvrn[v = getlca(stk[i], stk[i + 1])] ^ vtim)
      vvrn[v] = vtim, stk[++stktop] = v;
  sort(stk + 1, stk + stktop + 1, cmp);
  bin[bintop = 1] = stk[1];
  for (int i = 2; i <= stktop; i++) {
    while (id[stk[i]] >= id[bin[bintop]] + siz[bin[bintop]]) bintop--;
    addedge(bin[bintop], stk[i]);
    bin[++bintop] = stk[i];
  }
}
int son[150010];
int dfs1(int cur) {
  int siz = 1, maxs = 0;
  son[cur] = 0;
  for (int i = last[cur], v, t; i; i = edge[i].nxt) {
    siz += (t = dfs1(v = edge[i].to));
    if (!son[cur] || maxs < t) maxs = t, son[cur] = v;
  }
  return siz;
}
vector<int> qt1[150010];
vector<pair<int, int> > qt2[150010];
void dfs3(int o, int cur, int rt) {
  for (int i = 0; i < qt1[o].size(); i++) {
    int v = qt1[o][i];
    int len = dep[cur] - dep[rt] + 1, t;
    if (len >= k)
      t = dep[v] - dep[rt] - 1;
    else if (k - len > dep[v] - dep[rt] - 1)
      continue;
    else
      t = dep[v] - dep[rt] - 1 - k + len;
    v = lift(v, t);
    ans += ask(id[v] + siz[v] - 1) - ask(id[v] - 1);
  }
  for (int i = last[o]; i; i = edge[i].nxt) dfs3(edge[i].to, cur, rt);
}
void dfs4(int o) {
  for (int i = 0; i < qt1[o].size(); i++) {
    int v = qt1[o][i];
    add(id[v], 1);
  }
  for (int i = last[o]; i; i = edge[i].nxt) dfs4(edge[i].to);
}
void dfs2(int cur, int rt) {
  if (!son[cur]) {
    btim++;
    for (int i = 0; i < qt1[cur].size(); i++) {
      int v = qt1[cur][i], u = v;
      int len = dep[cur] - dep[rt] + 1, t;
      if (len >= k)
        t = dep[v] - dep[rt] - 1;
      else if (k - len > dep[v] - dep[rt] - 1) {
        add(id[u], 1);
        continue;
      } else
        t = dep[v] - dep[rt] - 1 - k + len;
      v = lift(v, t);
      ans += ask(id[v] + siz[v] - 1) - ask(id[v] - 1);
      add(id[u], 1);
    }
    return;
  }
  for (int i = last[cur], v; i; i = edge[i].nxt)
    if ((v = edge[i].to) ^ son[cur]) dfs2(v, rt);
  dfs2(son[cur], rt);
  for (int i = 0; i < qt1[cur].size(); i++) {
    int v = qt1[cur][i], u = v;
    int len = dep[cur] - dep[rt] + 1, t;
    if (len >= k)
      t = dep[v] - dep[rt] - 1;
    else if (k - len > dep[v] - dep[rt] - 1) {
      add(id[u], 1);
      continue;
    } else
      t = dep[v] - dep[rt] - 1 - k + len;
    v = lift(v, t);
    ans += ask(id[v] + siz[v] - 1) - ask(id[v] - 1);
    add(id[u], 1);
  }
  for (int i = last[cur], v; i; i = edge[i].nxt)
    if ((v = edge[i].to) ^ son[cur]) dfs3(v, cur, rt), dfs4(v);
}
void dfs6(int cur) {
  for (int i = 0; i < qt2[cur].size(); i++) {
    int v = qt2[cur][i].second;
    ans += ask(n) - (v ? ask(id[v] + siz[v] - 1) - ask(id[v] - 1) : 0);
  }
  for (int i = last[cur]; i; i = edge[i].nxt) dfs6(edge[i].to);
}
void dfs7(int cur) {
  for (int i = 0; i < qt2[cur].size(); i++) {
    int v = qt2[cur][i].first;
    add(id[v], 1);
  }
  for (int i = last[cur]; i; i = edge[i].nxt) dfs7(edge[i].to);
}
void dfs5(int cur, int rt) {
  if (dep[cur] - dep[rt] < k) {
    for (int i = last[cur]; i; i = edge[i].nxt) dfs5(edge[i].to, rt);
    return;
  }
  if (!son[cur]) {
    btim++;
    for (int i = 0; i < qt2[cur].size(); i++) {
      int u = qt2[cur][i].first, v = qt2[cur][i].second;
      ans += ask(n) - (v ? ask(id[v] + siz[v] - 1) - ask(id[v] - 1) : 0);
      add(id[u], 1);
    }
    return;
  }
  for (int i = last[cur], v; i; i = edge[i].nxt)
    if ((v = edge[i].to) ^ son[cur]) dfs5(v, rt);
  dfs5(son[cur], rt);
  for (int i = 0; i < qt2[cur].size(); i++) {
    int u = qt2[cur][i].first, v = qt2[cur][i].second;
    ans += ask(n) - (v ? ask(id[v] + siz[v] - 1) - ask(id[v] - 1) : 0);
    add(id[u], 1);
  }
  for (int i = last[cur], v; i; i = edge[i].nxt)
    if ((v = edge[i].to) ^ son[cur]) dfs6(v), dfs7(v);
}
void clear() {
  for (int i = 1; i <= stktop; i++)
    last[stk[i]] = 0, vector<int>().swap(qt1[stk[i]]),
    vector<pair<int, int> >().swap(qt2[stk[i]]);
  cnt = 0;
  stktop = 0;
}
}  // namespace V
void dfs2(int cur) {
  V::vtim++;
  for (int i = 0; i < qry[cur].size(); i++) {
    int u = rec[qry[cur][i]].u, v = rec[qry[cur][i]].v;
    V::push(u);
    V::push(v);
  }
  V::build();
  V::dfs1(cur);
  for (int i = 0; i < qry[cur].size(); i++) {
    int u = rec[qry[cur][i]].u, v = rec[qry[cur][i]].v;
    if (u == cur || v == cur) continue;
    V::qt1[id[u] < id[v] ? u : v].push_back(id[u] < id[v] ? v : u);
  }
  for (int i = V::last[cur]; i; i = V::edge[i].nxt) V::dfs2(V::edge[i].to, cur);
  for (int i = 0; i < qry[cur].size(); i++) {
    int u = rec[qry[cur][i]].u, v = rec[qry[cur][i]].v;
    if (u ^ cur)
      V::qt2[u].push_back(
          (pair<int, int>){v, v ^ cur ? lift(v, dep[v] - dep[cur] - 1) : 0});
    if (v ^ cur)
      V::qt2[v].push_back(
          (pair<int, int>){u, u ^ cur ? lift(u, dep[u] - dep[cur] - 1) : 0});
  }
  for (int i = V::last[cur]; i; i = V::edge[i].nxt) {
    V::dfs5(V::edge[i].to, cur);
  }
  V::clear();
  for (int i = last[cur], v; i; i = edge[i].nxt)
    if ((v = edge[i].to) ^ gnd[cur][0]) dfs2(v);
}
int main() {
  n = read(), m = read(), k = read();
  if (k == n) return puts("0"), 0;
  for (int i = 1; i < n; i++) addedge(read(), read());
  dfs0(1, 1);
  for (int i = 1; i <= m; i++) {
    int u = read(), v = read();
    rec[i] = (Rec){u, v};
    qry[getlca(u, v)].push_back(i);
  }
  dfs1(1);
  dfs2(1);
  printf("%I64d\n", ans);
  return 0;
}
