#include <bits/stdc++.h>
using namespace std::literals::string_literals;
using i64 = std::int_fast64_t;
using std::cout;
using std::cerr;
using std::endl;
using std::cin;

template<typename T>
std::vector<T> make_v(size_t a){return std::vector<T>(a);}

template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts){
  return std::vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}

class lowest_common_ancestor {
	std::vector<std::vector<size_t>> g, parent;
	std::vector<size_t> depth;
	
	const size_t logN = 20;

	private:
	void dfs(size_t v, int par = -1, size_t d = 0) {
		parent[0][v] = par;
		depth[v] = d;
		
		for(auto e:g[v]) {
			if(e == par) continue;
			
			dfs(e, v, d + 1);
		}
	}
	void build() {
		for(int i = 0; i < g.size(); i++) if(depth[i] == -1) dfs(i);
		
		for(int k = 0; k < logN - 1; k++) {
			for(int i = 0; i < g.size(); i++) {
				if(parent[k][i] == -1) parent[k + 1][i] = -1;
				else parent[k + 1][i] = parent[k][parent[k][i]];
			}
		}
	}

	public:
	lowest_common_ancestor() {}
	lowest_common_ancestor(int n) : g(n), depth(n, -1) {
		parent.assign(logN, std::vector<size_t>(n, -1));
	}
	void add_edge(const size_t & u, const size_t & v) {
		g[u].push_back(v);
		g[v].push_back(u);
	}
	const size_t query(size_t u, size_t v) {
		static bool built = false;
		if(!built) {
			build();
			built = true;
		}

		if(depth[u] > depth[v]) std::swap(u, v);
		for(int k = 0; k < logN; k++) {
			if(((depth[v] - depth[u]) >> k) & 1) v = parent[k][v];
		}
		if(u == v) return u;

		for(int k = logN - 1; k >= 0; k--) {
			if(parent[k][u] == parent[k][v]) continue;

			u = parent[k][u];
			v = parent[k][v];			
		}		
		return parent[0][u];
	}
};

class union_find_tree {
public:
	using size_type = std::int_fast32_t;
	using container = std::vector<size_type>;
	
protected:
	container data;
	size_type comp_sz;

private:
	const size_type find(size_type k) {
		if(data[k] < 0) return k;
		return data[k] = find(data[k]);
	}

public:
	union_find_tree() = default;
	union_find_tree(const union_find_tree &) = default;
	union_find_tree(union_find_tree &&) = default;

	union_find_tree(const size_type & N) : data(N, -1), comp_sz(N) {}

	union_find_tree & operator=(const union_find_tree &) = default;
	union_find_tree & operator=(union_find_tree &&) = default;
	
	const bool unite(size_type x, size_type y) {
		x = find(x); y = find(y);
		if(x == y) return false;
		if(data[x] > data[y]) std::swap(x, y);
		
		data[x] += data[y];
		data[y] = x;
		comp_sz--;
		return true;
	}
	
	const bool is_same(const size_type & x, const size_type & y) { return find(x) == find(y); }
	const size_type size() const { return data.size(); }
	const size_type size(const size_type & k) { return -data[find(k)]; }
	const size_type comp(const size_type & k) { return find(k); };
	const size_type comp_size() const { return comp_sz; }
	const size_type operator[](const size_type & k) { return find(k); }
	
	void swap(union_find_tree & r) {
		using std::swap;
		data.swap(r.data);
		swap(comp_sz, r.comp_sz);
	}
	void clear(const size_type & N = 0) {
		data.assign(N, -1);
		comp_sz = N;
	}
};

int main() {
	i64 n; scanf("%lld", &n);
	lowest_common_ancestor lca(n);
	std::vector<int> a(n - 1), b(n - 1);
	std::vector<std::vector<int>> g(n);
	for(int i = 0; i < n - 1; i++) {
		scanf("%d%d", &a[i], &b[i]);
		a[i]--; b[i]--;
		
		lca.add_edge(a[i], b[i]);
		g[a[i]].push_back(i);
		g[b[i]].push_back(i);
	}

	int m; scanf("%d", &m);
	std::vector<int> u(m), v(m);
	for(int i = 0; i < m; i++) {
		scanf("%d%d", &u[i], &v[i]);

		u[i]--; v[i]--;
	}
	
	// solve
	std::vector<int> parent(n, -1);
	auto dfs = [&](auto&& dfs, int v, int par) -> void {
		for(auto id: g[v]) {
			int to = a[id] ^ b[id] ^ v;
			if(to == par) continue;
			parent[to] = v;
			dfs(dfs, to, v);
		}
	};
	dfs(dfs, 0, -1);
	
	std::vector<i64> dp(1 << m, 0);
	for(int i = 0; i < dp.size(); i++) {
		i64 cnt = 0;
		union_find_tree uf(n);
		for(int k = 0; k < m; k++) {
			if(!(i >> k & 1)) continue;

			int now = v[k], com = lca.query(u[k], v[k]);
			if(v[k] != com) {
				while(parent[now] != -1) {
					if(uf.unite(now, parent[now])) cnt++;
					now = parent[now];
					if(now == com or now == -1) break;
				}
			}

			now = u[k];
			if(u[k] != com) {
				while(parent[now] != -1) {
					if(uf.unite(now, parent[now])) cnt++;
					now = parent[now];
					if(now == com or now == -1) break;
				}
			}
		}

		dp[i] = 1LL << ((n - 1) - cnt);
	}

	for(int i = 0; i < m; i++) {
		for(int j = 0; j < dp.size(); j++) {
			if(j >> i & 1) continue;
			dp[j] -= dp[j ^ (1 << i)];
		}
	}

	printf("%lld\n", dp[0]);
	return 0;
}


Measured memory_bytes: 8576