// #define _GLIBCXX_DEBUG // for STL debug (optional)
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <cfloat>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <fstream>
#include <functional>
#include <bitset>
using namespace std;
using ll = long long int;
using int64 = long long int;
 
template<typename T> void chmax(T &a, T b) {a = max(a, b);}
template<typename T> void chmin(T &a, T b) {a = min(a, b);}
template<typename T> void chadd(T &a, T b) {a = a + b;}
 
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const int INF = 1LL << 29;
const ll LONGINF = 1LL << 60;
const ll MOD = 1000000007LL;

map< vector<int>, int > hs_to_h;

vector< vector< vector<int> > > forest_to_graph(const vector< vector<int> > &G) {
    int N = G.size();
    vector< vector< vector<int> > > graphs;

    vector<int> v_to_id(N, -1), v_to_group(N, -1);
    vector<bool> checked(N);
    for(int i=0; i<N; i++) {
        if(checked[i]) continue;
        int id = 0, group_id = graphs.size();
        queue<int> que;
        checked[i] = true;
        v_to_group[i] = group_id;
        v_to_id[i] = id++;
        que.emplace(i);
        while(que.size()) {
            int cur = que.front(); que.pop();
            for(auto to : G[cur]) {
                if(checked[to]) continue;
                checked[to] = true;
                v_to_group[to] = group_id;
                v_to_id[to] = id++;
                que.emplace(to);
            }
        }
        graphs.emplace_back(vector< vector<int> >(id));
    }

    for(int i=0; i<N; i++) {
        int group_id = v_to_group[i];
        for(auto j : G[i]) {
            int u = v_to_id[i], v = v_to_id[j];
            graphs[group_id][u].emplace_back(v);
        }
    }
    return graphs;
}

int get_hash(const vector< vector<int> > &G, int c) {
    auto dfs = [&](auto &&self, int cur, int par) -> int {
        vector<int> children;
        for(auto to : G[cur]) {
            if(to == par) continue;
            children.emplace_back(self(self, to, cur));
        }
        
        sort(children.begin(), children.end());
        if(hs_to_h.count(children)) return hs_to_h[children];
        int s = hs_to_h.size();
        return hs_to_h[children] = s;
    };
    return dfs(dfs, c, -1);
}

vector<int> get_hashes(const vector< vector<int> > &G) {
    int N = G.size();
    vector<int> d1(N), d2(N), d3(N);

    auto dfs = [&](auto &&self, int cur, int par, vector<int> &d) -> void {
        for(auto to : G[cur]) {
            if(to == par) continue;
            d[to] = d[cur] + 1;
            self(self, to, cur, d);
        }
    };

    dfs(dfs, 0, -1, d1);
    int v0 = max_element(d1.begin(), d1.end()) - d1.begin();
    dfs(dfs, v0, -1, d2);
    int v1 = max_element(d2.begin(), d2.end()) - d2.begin();
    dfs(dfs, v1, -1, d3);

    int m = N;
    vector<int> centroids;
    for(int i=0; i<N; i++) {
        int d = max(d2[i], d3[i]);
        if(m > d) {
            centroids.clear();
            m = d;
        }
        if(m == d) {
            centroids.emplace_back(i);
        }
    }

    vector<int> hashes;
    for(auto c : centroids) hashes.emplace_back(get_hash(G, c));
    return hashes;
}

int main() {
    int N, M; scanf("%d%d", &N, &M);
    vector< vector<int> > G(N);
    for(int i=0; i<M; i++) {
        int u, v; scanf("%d%d", &u, &v);
        u--; v--;
        G[u].emplace_back(v);
        G[v].emplace_back(u);
    }

    vector< vector< vector<int> > > graphs = forest_to_graph(G);

    int V; scanf("%d", &V);
    vector< vector<int> > T(V);
    for(int i=0; i+1<V; i++) {
        int u, v; scanf("%d%d", &u, &v);
        u--; v--;
        T[u].emplace_back(v);
        T[v].emplace_back(u);
    }

    int ans = 0;
    vector<int> tree_hash = get_hashes(T);
    for(auto g : graphs) {
        vector<int> g_hash = get_hashes(g);
        bool ok = false;
        for(auto h1 : g_hash) {
            for(auto h2 : tree_hash) {
                ok |= (h1 == h2);
            }
        }
        if(ok) ans++;
    }
    printf("%d\n", ans);
    return 0;
}



Measured memory_bytes: 91188