#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define int ll

#define REP(i,n) for(int i=0;i<n;++i)
#define ALL(name) name.begin(),name.end()
#define SORT(name) sort(name.begin(), name.end())
#define ZERO(p) memset(p, 0, sizeof(p))
#define MINUS(p) memset(p, -1, sizeof(p))

const ll LLINF = (1LL<<60);
const int INF = (1LL<<30);
const double DINF = std::numeric_limits<double>::infinity();
const int MOD = 1000000007;
#define MAX_N 51
#define MAX_M 21

template <typename T, typename U>
class Dijkstra {
    private:
        struct Edge {
            T to;   // 有向辺の行先頂点
            U cost;  // 辺の重み
        };
        typedef pair<U, T> P;       // first: 最短距離 second: 頂点 id
    public:
        // コンストラクタ
        // v … 頂点数, inf: …「無限大」とする値
        Dijkstra() {}
        Dijkstra(T v, U inf) { Init(v, inf); }
        void Init(T v, U inf) {
            m_V = v;
            m_Inf = inf;
            m_G.assign(m_V, vector<Edge>());
        }
        // 有向辺の追加。負のコストは未対応
        void AddDirEdge(T from, T to, U cost) { m_G[from].push_back({to, cost}); }
        // 無向辺の追加。負のコストは未対応
        void AddUndirEdge(T from, T to, U cost) {
            AddDirEdge(from, to, cost);
            AddDirEdge(to, from, cost);
        }
        // 始点 s から各頂点への最短経路の導出 O(E log V)
        // Calc を連続で行うことはできない。その場合は m_Dist と m_Prev の再初期化が必要
        void Calc(T s) {
            m_Dist.assign(m_V, m_Inf);
            m_PrevP.assign(m_V, -1);
            // 最短距離が短い順で cand を取り出す
            // 頂点 P.second まで P.first のコストで来れたことを情報として入れておく
            priority_queue<P, vector<P>, greater<P> > cand;
            m_Dist[s] = 0;  // 始点のコストは 0
            cand.push(P(0, s));
            while(!cand.empty()) {
                P p = cand.top(); cand.pop();     // cand のトップを取り出す
                T v = p.second;
                // 頂点 v まで最短経路が、 cand から取り出したものより既に小さいなら何もしない
                if(m_Dist[v] < p.first){ continue; }
                // 現在見ている頂点から延びている辺を全て見る
                for(Edge e : m_G[v]) {
                    if(m_Dist[e.to] > m_Dist[v] + e.cost) {
                        // 現在の最短経路より短くなるなら更新
                        m_Dist[e.to] = m_Dist[v] + e.cost;
                        m_PrevP[e.to] = v;
                        cand.push(P(m_Dist[e.to], e.to));
                    }
                }
            }
        }
        // 始点 s から頂点 t への最短距離を返す O(1)
        // 前処理として Calc(s) が必要
        U GetDist(T t) { return m_Dist[t]; }
        // 始点 s から頂点 t までの経路を vector に入れて返す (s と t 含む)
        // O(V') … V' は最短経路の頂点数
        // 前処理として Calc(s) が必要
        vector<T> GetPath(T t) {
            vector<T> path;
            for(; t != -1; t = m_PrevP[t]) { path.push_back(t); }  // t が s になるまで prev_p[t] を辿っていく
            // このままだと t->s の順になっているので逆順にする
            reverse(path.begin(), path.end());
            return path;
        }
    private:
        T m_V;                // 頂点の数
        U m_Inf;              // 無限の代わりとして扱う値
        vector< vector<Edge> > m_G; // 頂点 i から延びている辺の vector(隣接リスト)
        vector<U> m_Dist;           // 各頂点への最短コスト。つまり答え
        vector<T> m_PrevP;          // 最短経路の各頂点を保存(経路復元で利用)
};

int N, M;
vector< pair<ll, ll> > AB;
vector< pair<ll, ll> > UV;

ll dp[MAX_N][(1LL << MAX_M) + 1];

int edge_to_id[MAX_N][MAX_N];           // i, j の辺の id を返す。ない場合は -1

vector<int> m_cond;                     // 条件 i [0, M) を満たすために必要な黒くすべき辺のパターン（ビット）
vector<int> e_cond;                     // 辺 i [0, N-1) を黒くしたときに満たされる条件のパターン（ビット）

Dijkstra<int, ll> dk;

// i 番目の辺を見ていて、現状満たされている条件が pat のときの
// 条件を満たしている経路のパターン数
ll dfs(int i, int pat) {
    if(i >= N - 1) {
        int ans = (1LL << M) - 1;
        if(pat == ans) { return 1; }
        return 0;
    }

    ll& ret = dp[i][pat];
    if(~ret) { return ret; }
    ret = 0;

    // この辺を黒くした場合
    ret = dfs(i + 1, pat | e_cond[i]);

    // この辺を黒くしない場合
    ret += dfs(i + 1, pat);

    return ret;
}

ll solve() {
    REP(i, N - 1) {
        int a = AB[i].first;
        int b = AB[i].second;
        dk.AddUndirEdge(a, b, 1);

        if(a > b) { swap(a, b); }
        edge_to_id[a][b] = i;
        edge_to_id[b][a] = i;
    }
    REP(i, M) {
        int u = UV[i].first;
        int v = UV[i].second;
        // u - v の経路を取得
        dk.Calc(u);
        auto path = dk.GetPath(v);
        ll bit_pat = 0;
        for(int j = 0; j < path.size() - 1; ++j) {
            // 辺 id の取得
            int e_id = edge_to_id[path[j]][path[j+1]];
            assert(e_id >= 0);
            bit_pat |= (1LL << e_id);
        }
        m_cond.push_back(bit_pat);
    }

    // e_cond の作成
    e_cond.assign(N, 0);
    for(int e_id = 0; e_id < N - 1; ++e_id) {
        for(int i = 0; i < M; ++i) {
            if((m_cond[i] >> e_id) & 1) {
                e_cond[e_id] |= (1LL << i);
            }
        }
    }

    MINUS(dp);
    return dfs(0, 0);
}

signed main() {
    cin.tie(0); cout.tie(0);
    ios::sync_with_stdio(false);

    cin >> N;
    dk.Init(N, LLINF);
    MINUS(edge_to_id);
    REP(i, N - 1) {
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        AB.push_back(make_pair(a, b));
    }

    cin >> M;
    REP(i, M) {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        UV.push_back(make_pair(u, v));
    }

    printf("%lld\n", solve());

    return 0;
}


Measured memory_bytes: 835968