#include<iostream>
#include<string>
#include<vector>
#include<utility>
#include<algorithm>
#include<map>
#include<set>
#include<cstdlib>
#include<cmath>
#include<numeric>
#include<iomanip>
#include<functional>
#include<cstdlib>
#include<queue>
#include<deque>
#include<cassert>
#include<stack>
#include <iterator>     // std::back_inserter
const double PI = acos(-1);
using namespace std;
using ll =long long;
#define rep(i,n)for(ll i=0;i<(n);i++)
const int mod = 1000000007;
const ll inf = 1e18 + 1;
//int ctoi(char c) {
//	if (c >= '0' && c <= '9') {
//		return c - '0';
//	}
//	return 0;
//}
//
ll gcd(ll a, ll b) {
	if (a % b == 0) {
		return b;
	}
	else {
		return gcd(b, a % b);
	}
}
//ll lcm(ll a, ll b) {
//	return a * b / gcd(a, b);
//};
//fixed << setprecision(2)


///*Union Find*/
//#define MAX_N 200000
//#define MAX_M 200000
//vector<ll>par(MAX_N);
//vector<ll>ran(MAX_N);
//void init(ll N) {
//	rep(i, N) {
//		par[i] = i;
//		ran[i] = 0;
//	}
//}
//ll find(ll x) {
//	if (par[x] == x) {
//		return x;
//	}
//	else {
//		return par[x] = find(par[x]);
//	}
//}
//void unite(ll x,ll y) {
//	x = find(x);
//	y = find(y);
//	if (x == y)return;
//	if (ran[x] < ran[y]) {
//		par[x] = y;
//
//	}
//	else {
//		par[y] = x;
//		if (ran[x] == ran[y])ran[x]++;
//	}
//}
//bool same(ll x, ll y) {
//	return find(x) == find(y);
//}
////UnionFind

//dfs
//if (nh < 0 || nh >= H || nw < 0 || nw >= W) continue;
//dfs

//桁和を求める
//int digsum(ll n) {
//	int res = 0;
//	while (n > 0) {
//		res += n % 10;
//		n /= 10;
//	}
//	return res;
//}
//桁和を求める
//cin,coutを早くする
//ios::sync_with_stdio(false);
//cin coutを早くする。
int main() {
	ios::sync_with_stdio(false);
	int N, M;
	cin >> N >> M;
	vector<int>a(M),b(M);
	rep(i, M) {
		cin >> a[i] >> b[i];
	}
	int K; cin >> K;
	vector<int>c(K),d(K);
	rep(i, K) {
		cin >> c[i] >> d[i];
	}
	int n = K;
	ll ans=0;
	for (int bit = 0; bit < (1 << n); ++bit) {
		vector<int> S;
		for (int i = 0; i < n; ++i) {
			if (bit & (1 << i)) {
				S.push_back(i);
			}
		}
		vector<bool>ret(K,false);
		map<int,bool>tmp;
		for (int i = 0; i < (int)S.size(); ++i) {
			ret[S[i]] = true;
		}
		for (int i = 0; i < K; i++) {
			if (ret[i]) {
				tmp[c[i]] = true;
			}
			else {
				tmp[d[i]]=true;
			}
		}
		ll tmpans=0;
		rep(i, M) {
			if (tmp[a[i]] && tmp[b[i]])tmpans++;
		}
		ans = max(tmpans, ans);

	}
	cout << ans;
}

#include <bits/stdc++.h>
using namespace std;

int main(){
  int n,m;
  cin >> n >> m;
  vector<vector<int>> jyou(n+1,vector<int>(n+1,0));
  for(int i=0;i<m;i++){
    int a,b;
    cin >> a >> b;
    jyou.at(a).at(b)++;
    jyou.at(b).at(a)++;
  }
  int k;
  cin >> k;
  vector<int> c(k);
  vector<int> d(k);
  for(int i=0;i < k;i++){
    cin >> c.at(i) >> d.at(i);
  }
  int answer = 0;
  for (int tmp = 0; tmp < (1 << k); tmp++) {
    bitset<16> s(tmp);  // 最大20個なので20ビットのビット列として扱う
 
    // ビット列の1のビットに対応する整数を選んだとみなして総和を求める
    set<int> x;
    int ans = 0;
    for (int i = 0; i < k; i++) {
      if (s.test(i)) {
        x.insert(d.at(i));
      }
      else{
        x.insert(c.at(i));
      }
    }
    int y = (int)x.size();
    for(auto j = x.begin(); j != x.end(); ++j) {
      for(auto l = next(j); l != x.end(); ++l) {
        if(jyou.at(*j).at(*l) > 0){
          ans+=jyou.at(*j).at(*l);
        }
      }
    }
    answer = max(ans,answer);
  }
  
  cout << answer << endl;
 
}     