/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author cherrypi59
 */

#pragma GCC optimize ("O2")
#pragma GCC optimize ("tree-vectorize")
#pragma GCC target ("sse4")

#include <bits/stdc++.h>
#define FOR(i, a, b) for(int i=(a);i<(b);++i)
#define FFOR(i, a, b) FOR(i, a, b+1)
#define REP(i, n) FOR(i, 0, n)
#define RREP(i, n) FOR(i, 1, n+1)
#define ALL(v) (v).begin(), (v).end()
#define RALL(v) (v).rbegin(), (v).rend()
#define LEN(x) (int)(x).size()
#define DUMP(x) cerr<<__LINE__<<' '<<#x<<"="<<(x)<<endl;
#define popcnt(x) __builtin_popcount(x)
#define popcntll(x) __builtin_popcountll(x)
#define pb push_back
#define eb emplace_back
#define mp make_pair

using namespace std;
using lint = long long;
using pii =  pair<int, int>;
using pll =  pair<lint, lint>;
template <typename T> using vc = vector<T>;
template <typename T> using vvc = vector<vector<T>>;
template <typename T> inline bool chmax(T &a, T b){if(a<b){a = b; return true;} return false;}
template <typename T> inline bool chmin(T &a, T b){if(a>b){a = b; return true;} return false;}

constexpr lint ten(int n) {return n==0 ? 1 : ten(n-1)*10;}

struct edge{int from, to, id;};

class UnionFind{
private:
    int n;
    vector<int> parent, r;

    int _find(int x){
        assert(x<n);
        if(parent[x] == x) return x;
        else return parent[x] = _find(parent[x]);
    }

    void _unite(int x, int y){
        x = _find(x); y = _find(y);
        if(x == y) return;
        if(r[x]<r[y]){
            parent[x] = y;
            r[y] += r[x];
        }
        else{
            parent[y] = x;
            r[x] += r[y];
        }
    }

public:
    int find(int x){
        return _find(x);
    }

    void unite(int x, int y){
        _unite(x, y);
    }

    int count(int x){
        return r[_find(x)];
    }

    int operator[](int i){
        return _find(i);
    }

    UnionFind() : n(0){}

    explicit UnionFind(size_t _n) : n(_n){
        parent = vector<int>(n);
        r = vector<int>(n);
        for(int i=0;i<n;i++){
            parent[i] = i;
            r[i] = 1;
        }
    }
};

class FTreeAndConstraints {
public:
    void solve(std::istream& in, std::ostream& out){
        ios_base::sync_with_stdio(false);
        in.tie(nullptr), out.tie(nullptr);
        int N, M;
        in>>N;
        vc<edge> E(N-1);
        REP(i, N-1){
            in>>E[i].from>>E[i].to;
            E[i].from--, E[i].to--;
            E[i].id = i;
        }
        in>>M;
        vc<pii> C(M);
        REP(i, M){
            in>>C[i].first>>C[i].second;
            C[i].first--, C[i].second--;
        }
        vc<lint> f(M, 0);
        REP(i, N-1){
            UnionFind uf(N);
            REP(j, N-1){
                if(i==j) continue;
                uf.unite(E[j].from, E[j].to);
            }
            REP(j, M){
                if(uf.find(C[j].first)!=uf.find(C[j].second)) f[j] |= 1ll << i;
            }
        }
        lint ans = 0;
        REP(mask, 1<<M){
            int cnt = 0;
            lint emask = 0;
            REP(j, M){
                if(mask>>j&1){
                    ++cnt;
                    emask |= f[j];
                }
            }
            int can = N - 1;
            REP(j, N-1){
                if(emask>>j&1) --can;
            }
            if(cnt&1) ans -= (1ll<<can);
            else ans += (1ll<<can);
        }
        out<<ans<<'\n';
    }
};


int main() {
	FTreeAndConstraints solver;
	std::istream& in(std::cin);
	std::ostream& out(std::cout);
	solver.solve(in, out);
	return 0;
}


Measured memory_bytes: 3640