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;
typedef long long ll;
#define lc (t[p].ch[0])
#define rc (t[p].ch[1])
const int N=150010;
inline int lowbit(int x)
{
	return x&(-x);
}
int n,m,K;
ll ans=0;
pair<int,int> p[N];
vector<int> rlca[N];
namespace fenwick
{
	int dat[N];
	inline void modify(int p,int v)
	{
		for(;p;p-=lowbit(p))dat[p]+=v;
	}
	inline int query(int p)
	{
		int ret=0;
		for(;p<=n;p+=lowbit(p))ret+=dat[p];
		return ret;
	}
	inline void modify(int l,int r,int v)
	{
		modify(l-1,-v);
		modify(r,v);
	}
	inline void init()
	{
		memset(dat,0,sizeof(dat));
	}
}
namespace sgt
{
	class node
	{
		public:
			int ch[2],sum;
	}t[10000000];
	int nodecnt=0;
	void init()
	{
		nodecnt=0;
	}
	void modify(int &p,int l,int r,int pos,int v)
	{
		if(!p)
		{
			p=++nodecnt;
			t[p].sum=t[p].ch[0]=t[p].ch[1]=0;
		}
		t[p].sum+=v;
		if(l==r)return;
		int mid=(l+r)>>1;
		if(pos<=mid)modify(lc,l,mid,pos,v);
		else modify(rc,mid+1,r,pos,v);
	}
	int query(int p,int l,int r,int ql,int qr)
	{
		if(!p)return 0;
		if(ql<=l&&r<=qr)return t[p].sum;
		int mid=(l+r)>>1,ret=0;
		if(ql<=mid)ret=query(lc,l,mid,ql,qr);
		if(qr>mid)ret+=query(rc,mid+1,r,ql,qr);
		return ret;
	}
	int merge(int x,int y)
	{
		if(!x||!y)return x|y;
		t[x].ch[0]=merge(t[x].ch[0],t[y].ch[0]);
		t[x].ch[1]=merge(t[x].ch[1],t[y].ch[1]);
		t[x].sum=t[t[x].ch[0]].sum+t[t[x].ch[1]].sum;
		return x;
	}
}
namespace tree
{
	vector<int> v[N];
	int st[N][18],dep[N],L[N],R[N],tim,siz[N],ch[N];
	void addedge(int s,int e)
	{
		v[s].push_back(e);
		v[e].push_back(s);
	}
	inline int lca(int x,int y)
	{
		if(dep[x]<dep[y])swap(x,y);
		for(int i=17;i>=0;i--)
			if(dep[st[x][i]]>=dep[y])x=st[x][i];
		if(x==y)return x;
		for(int i=17;i>=0;i--)
			if(st[x][i]!=st[y][i])x=st[x][i],y=st[y][i];
		return st[x][0];
	}
	inline int jump(int x,int step)
	{
		for(int i=17;i>=0;i--)if((step>>i)&1)x=st[x][i];
		return x;
	}
	inline void dfs1(int np,int fath)
	{
		siz[np]=1;
		dep[np]=dep[fath]+1;
		st[np][0]=fath;
		for(int i=1;i<18;i++)st[np][i]=st[st[np][i-1]][i-1];
		for(int &x:v[np])
		{
			if(x==fath)continue;
			dfs1(x,np);
			siz[np]+=siz[x];
			if(!ch[np]||siz[ch[np]]<siz[x])ch[np]=x;
		}
	}
	inline void dfs2(int np,int fath)
	{
		L[np]=++tim;
		for(int &x:v[np])
		{
			if(x==fath||x==ch[np])continue;
			dfs2(x,np);
		}
		if(ch[np])dfs2(ch[np],np);
		R[np]=tim;
	}
	vector<int> pt[N],qry[N];
	int rt[N];
	inline void dfs4(int np,int fath,int root)
	{
		rt[np]=0;pt[np].clear();
		for(int &y:qry[np])
		{
			int pos=-1;
			if(dep[np]-dep[root]>=K)pos=root;
			else
			{
				int U=p[y].first,V=p[y].second;
				int d=(dep[V]-dep[root])-(K-(dep[np]-dep[root]));
				if(d>=0)pos=jump(V,d);
			}
			if(pos!=-1)ans+=sgt::query(rt[np],1,n,L[pos],R[pos]);
			sgt::modify(rt[np],1,n,L[p[y].second],1);
		}
		pt[np].insert(pt[np].end(),qry[np].begin(),qry[np].end());
		qry[np].clear();
		for(int &x:v[np])
		{
			if(x==fath||(np==root&&x==ch[np]))continue;
			dfs4(x,np,root);
			if(pt[np].size()<pt[x].size())swap(pt[np],pt[x]),swap(rt[np],rt[x]);
			for(int &y:pt[x])
			{
				int pos;
				if(dep[np]-dep[root]>=K)pos=root;
				else
				{
					int U=p[y].first,V=p[y].second;
					int d=(dep[V]-dep[root])-(K-(dep[np]-dep[root]));
					if(d<0)continue;
					pos=jump(V,d);
				}
				ans+=sgt::query(rt[np],1,n,L[pos],R[pos]);
			}
			pt[np].insert(pt[np].end(),pt[x].begin(),pt[x].end());
			pt[x].clear();
			rt[np]=sgt::merge(rt[np],rt[x]);
		}
	}
	inline void dfs3(int np,int fath)
	{
		for(int &x:v[np])
		{
			if(x==fath)continue;
			dfs3(x,np);
		}
		for(int &x:rlca[np])ans+=fenwick::query(L[p[x].second]);//calculate the sum in the subtree
		for(int &x:rlca[np])
		{
			int V=p[x].second;
			if(dep[V]-dep[np]>=K)
			{
				V=jump(V,dep[V]-dep[np]-K);
				fenwick::modify(L[V],R[V],1);
			}
		}
		for(int &x:rlca[np])
		{
			ans+=fenwick::query(L[p[x].first]);//only calculate when lca(u1,u2)=np and lca(v1,v2)=np and the ones in subtree
			//because when this condition is satisfied,we will only calculate answer at the lower u point
			qry[p[x].first].push_back(x);
		}
		sgt::init();
		dfs4(np,fath,np);
		pt[np].clear();
		for(int &x:rlca[np])
		{
			int u=p[x].first;
			if(dep[u]-dep[np]>=K)
			{
				u=jump(u,dep[u]-dep[np]-K);
				fenwick::modify(L[u],R[u],1);
			}
		}
	}
}
int main()
{
//	freopen("data.in","r",stdin);
//	freopen("test.out","w",stdout);
	scanf("%d%d%d",&n,&m,&K);
	for(int i=1,a,b;i<n;i++)
	{
		scanf("%d%d",&a,&b);
		tree::addedge(a,b);
	}
	for(int i=1,a,b;i<=m;i++)
	{
		scanf("%d%d",&a,&b);
		p[i]=make_pair(a,b);
	}
	tree::dfs1(1,0);
	tree::dfs2(1,0);
	for(int i=1;i<=m;i++)
	{
		if(tree::L[p[i].first]>tree::L[p[i].second])swap(p[i].first,p[i].second);
		rlca[tree::lca(p[i].first,p[i].second)].push_back(i);
	}
	tree::dfs3(1,0);
	printf("%lld\n",ans);
	return 0;
}