#include <algorithm>

#include <bits/stdc++.h>
#include <cmath>
#include <limits>

using namespace std;
typedef long long LL;
static long long INF = (1LL<<62);

LL H, W, N, M;
map<pair<LL, LL>, int> L, B; //L電球、B：ブロック
map<LL, map<LL, int>> maplh, mapbh; //最初のキー：H座標、次のキー：W座標
map<LL, map<LL, int>> maplw, mapbw; //最初のキー：W座標、次のキー：H座標
map<pair<LL, LL>, int> mapLON; //照らされているブロック

// l<=x<=rなる最大のl、最小のrを返す
// lはxから小さい方向に進んで最初にぶち当たる値。ない場合は-INF
// rはxから大きい方向に進んで最小にぶち当たる値。ない場合はINF
void neighbor(map<LL, int> *m, LL x, LL &l, LL & r){
	if(m->size() == 0) {
		l = -INF;
		r = INF;
		return;
	}
	auto itr = m->lower_bound(x); //x<=itrの値
	if(itr == m->end()){ //endの場合はすべてのmapの要素に対して<x
		l = (--(m->end()))->first;
		r = INF;
		return;
	}
	else{
		r = itr->first;
	}
	if(itr == m->begin()){ //x <= mapのすべての値
		l = -INF;
		r = m->begin()->first;
	}
	else{
		itr--;
		l = itr->first;
	}
}

//座標(h, w)のブロックが照らされているかいなか
LL isOn(LL h, LL w){
	if(L.count(make_pair(h,w)) != 0){
		return 1LL;
	}
	if(B.count(make_pair(h,w)) != 0){
		return 0LL;
	}

	auto bh = &(mapbh[h]); auto bw = &(mapbw[w]);
	auto lh = &(maplh[h]); auto lw = &(maplw[w]);
	LL bp = -1, bq = W, br = -1, bs = H;
	LL lp = -1, lq = W, lr = -1, ls = H;

	LL ret = 0;
	//まず行に着目しててらされるか？
	neighbor(bh, w, bp, bq);
	neighbor(lh, w, lp, lq);
	if(lp == -INF && lq == INF){
		//行方向にランプなし
	}
	else{
		if(lp != -INF && bp <= lp && lp <= bq){ ret = 1LL; return ret;}
		if(lq != INF  && bp <= lq && lq <= bq){ ret = 1LL; return ret;}
	}

	neighbor(bw, h, br, bs);
	neighbor(lw, h, lr, ls);
	if(lr == -INF && ls == INF){
		//列方向にランプなし
	}
	else{
		if(lr != -INF && br <= lr && lr <= bs){ ret = 1LL; return ret; }
		if(ls != INF  && br <= ls && ls <= bs){ ret = 1LL; return ret; }
	}
	return ret;
}

int main(int argc, char* argv[]){
	cin.tie(0);
	ios::sync_with_stdio(false);

	cin >> H >> W >> N >> M;

	for(int i=0; i<N; i++){
		LL a, b; cin >> a >> b; a--; b--;
		auto p = make_pair(a, b);
		L[p] = 0;
		maplh[a][b] = 1;
		maplw[b][a] = 1;
	}
	for(int i=0; i<M; i++){
		LL c, d; cin >> c >> d; c--; d--;
		auto p = make_pair(c, d);
		B[p] = 0;
		mapbh[c][d] = 1;
		mapbw[d][c] = 1;
	}

	LL ans = 0;
	for(LL h=0; h<H; h++){
		for(LL w=0; w<W; w++){
			ans += isOn(h, w);
		}
	}
	printf("%lld\n", ans);
	return 0;
}

# include <bits/stdc++.h>
# define ull unsigned long long
# define ll long long
# define double long double
# define pll pair<ll,ll>
# define pb push_back
# define fi first
# define se second
# define mp make_pair
# define all(x) x.begin(),x.end()
# define fill(a,b) memset(a,b,sizeof(a))
# define gcd(m,n)  __gcd(m, n)
# define pr_double(x) cout << fixed << setprecision(9) << x

using namespace std;
const ll INF = 922337203685477110;
const ll N = 20;
const ll mod  = 1e9+7;
const ll M = 22;
vector <ll> g[N];
ll vis[N];
map <pll,ll> edge;

ll dp[1<<N];
bool con[1<<N];

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  ll n,m; cin>>n>>m;
  for(ll i=1;i<=m;i++)
  {
     ll x,y; cin>>x>>y;
     g[x].pb(y); g[y].pb(x);
     edge[{x,y}]=1; edge[{y,x}]=1;
  }
  for(ll i=0;i<(1<<n);i++)
  {
      dp[i]=INF;
      vector <ll> v;
      for(ll j=0;j<n;j++)
      {
          if(i&(1<<j)) v.pb(j+1);
      }
      ll ok=1;
      for(ll j=0;j<v.size();j++)
      {
          for(ll k=j+1;k<v.size();k++)
          {
              if(!edge[{v[j],v[k]}])
                {
                    ok=0; break;
                }
          }
          if(!ok) break;
      }
      con[i]=ok;
  }
  for(ll i=0;i<(1<<n);i++)
  {
      if(con[i]) dp[i]=1;
      else{
        for(ll j=i;j; j=(j-1)&i)
        {
            dp[i] = min(dp[i],dp[j]+dp[i^j]);
        }
      }
  }
  cout<<dp[(1<<n)-1]<<endl;
}
