#if 1
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <functional>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <ctime>
#include <cassert>
#include <sstream>
#include <iostream>
#include <bitset>

using namespace std;

typedef long long LL;
typedef long double LD;
typedef pair<int , int> pii;
typedef vector <int> veci;
typedef vector <veci> graph;
const LD eps = 1e-9;
const LD pi = acos(-1.0);
const int inf = 1000 * 1000 * 1000;
const LL inf64 = LL(inf) * inf;

#define mp make_pair
#define pb push_back
#define X first
#define Y second
#define iss istringstream
#define oss ostringstream
#define dbg(x) {cerr << #x << " = " << x << endl;}
#define dbgv(x) {cerr << #x << " ={"; for (int _i = 0; _i < x.size(); _i++) {if (_i) cerr << ", "; cerr << x[_i];} cerr << "}" << endl;}
#define NAME "problem"

struct LCAQueries
{
	static const int maxn = 100011;
	static const int maxlgn = 20;
	int up[maxn][maxlgn], tin[maxn], tout[maxn], timer;
	int lgn;
	
	void dfs(const graph &g, int u, int pred) {
		tin[u] = timer++;
		for(int i = 0; i < lgn; ++i)
			up[u][i] = i ? up[up[u][i - 1]][i - 1] : pred;
		for(int i = 0; i < g[u].size(); ++i)
			if(g[u][i] != pred)
				dfs(g, g[u][i], u);
		tout[u] = timer++;
	}
	
	void build(const graph &g, int s = 0) {
		lgn = 0; while((1 << lgn) <= g.size()) ++lgn;
		timer = 0; dfs(g, s, s);
	}
	
	bool anc(int u, int v)
	{ return tin[u] <= tin[v] && tout[v] <= tout[u]; }

	int get(int u, int v) {
		if(anc(u, v)) return u;
		if(anc(v, u)) return v;
		for(int i = lgn - 1; i >= 0; --i)
			if(!anc(up[u][i], v))
				u = up[u][i];
		return up[u][0];
	}

	int get_k_up(int u, int k)
	{
		for(int i = lgn - 1; i >= 0; --i)
			if(k & (1 <<i))
				u = up[u][i];
		return u;
	}
};

struct fenwick_t
{
	vector<int> f;
	void init(int n)
	{
		f.assign(n, 0);
	}

	void add(int idx, int val)
	{
		for (int i = idx; i < f.size(); i |= i + 1)
			f[i] += val;
	}

	int sum(int right)
	{
		int res = 0;
		for (int i = right; i >= 0; i &= i + 1, --i)
			res += f[i];
		return res;
	}
	int sum(int left, int right)
	{
		return sum(right) - sum(left - 1);
	}
};

LCAQueries qlca;
vector< pair<int, int> > pathes;
fenwick_t fenwick;
vector< vector<int> > by_lca;
LL intersected;
graph g;
void add_path(int id, int val)
{
	int u = pathes[id].first;
	int v = pathes[id].second;
	fenwick.add(qlca.tin[u], val);
	fenwick.add(qlca.tin[v], val);	
}

void dfs(int u, int pred = -1)
{
	LL cnt = by_lca[u].size();
	intersected += cnt * (cnt - 1) / 2;
	intersected += cnt * fenwick.sum(qlca.tin[u], qlca.tout[u]);

	for (size_t i = 0; i < by_lca[u].size(); ++i)
		add_path(by_lca[u][i], +1);

	for (size_t i = 0; i < g[u].size(); ++i)
	{
		int v = g[u][i];
		if (v == pred)
			continue;
		dfs(v, u);
	}

	for (size_t i = 0; i < by_lca[u].size(); ++i)
		add_path(by_lca[u][i], -1);
}

int main()
{
	//freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout);
	//freopen(NAME ".in","r",stdin);freopen(NAME ".out","w",stdout);

	int n;
	scanf("%d", &n);
	g.resize(n);
	for (int i = 1; i < n; ++i)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		--u; --v;
		g[u].push_back(v);
		g[v].push_back(u);
	}

	qlca.build(g);
	by_lca.resize(n);
	int k;
	scanf("%d", &k);
	for (int i = 0; i < k; ++i)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		--u; --v;
		pathes.push_back(make_pair(u, v));
		int w = qlca.get(u, v);
		by_lca[w].push_back(i);
	}

	fenwick.init(qlca.timer);
	intersected = 0;
	dfs(0);

	LL res = LL(k) * LL(k - 1) / 2LL;
	res -= intersected;
	cout << res << endl;
	return 0;
}
/*************************
*************************/
#endif
