#include <bits/stdc++.h>
#define INF 1000000007LL
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

//mincostflow
typedef pair<int,int> P;
struct edge{
	int to,cap,cost,rev;
	edge(int t,int c,int co,int r){
		to=t;
		cap=c;
		cost=co;
		rev=r;
	}
};

struct mincostflow{
	vector<edge> G[805];
	int h[805];
	int dist[805];
	int prevv[805],preve[805];

	void add_edge(int from,int to,int cap,int cost){
		G[from].push_back(edge(to,cap,cost,G[to].size()));
		G[to].push_back(edge(from,0,-cost,G[from].size()-1));
	}

	int min_cost_flow(int s,int t,int f,int V){
		int res=0;
		fill(h,h+V,0);
		while(f>0){
			priority_queue<P,vector<P>,greater<P> > que;
			fill(dist,dist+V,INF);
			dist[s]=0;
			que.push(P(0,s));
			while(que.size()){
				P p=que.top();
				que.pop();
				int v=p.second;
				if(dist[v]<p.first)continue;
				for(int i=0;i<G[v].size();i++){
					edge &e=G[v][i];
					if(e.cap>0 && dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){
						dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
						prevv[e.to]=v;
						preve[e.to]=i;
						que.push(P(dist[e.to],e.to));
					}
				}
			}
			if(dist[t]==INF)return INF;
			for(int v=0;v<V;v++){
				h[v]+=dist[v];
			}
			int d=f;
			for(int v=t;v!=s;v=prevv[v]){
				d=min(d,G[prevv[v]][preve[v]].cap);
			}
			f-=d;
			res+=d*h[t];
			for(int v=t;v!=s;v=prevv[v]){
				edge &e=G[prevv[v]][preve[v]];
				e.cap-=d;
				G[v][e.rev].cap+=d;
			}
		}
		return res;
	}
};

mincostflow mi;
mincostflow mi2;

int n,m;
int mf[101][101];
int fm[101][101];
int ans[3];

int main(void){
	scanf("%d%d",&n,&m);
	int S=(n+m)*3,T=S+1;
	int l;
	scanf("%d",&l);
	for(int i=0;i<l;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		mf[a][b]=2;
	}
	scanf("%d",&l);
	for(int i=0;i<l;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		mf[a][b]=1;
	}
	scanf("%d",&l);
	for(int i=0;i<l;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		fm[a][b]=2;
	}
	scanf("%d",&l);
	for(int i=0;i<l;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		fm[a][b]=1;
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			if(mf[i][j]==2 && fm[j][i]==2){
				mi.add_edge(i,n*3+j,1,-1000000);
				mi2.add_edge(i,n*3+j,1,1);
			}else if(mf[i][j]==2 && fm[j][i]==1){
				mi.add_edge(i,n*3+m+j,1,-1000);
				mi2.add_edge(i,n*3+m+j,1,1);
			}else if(mf[i][j]==1 && fm[j][i]==2){
				mi.add_edge(n+i,n*3+j,1,-1000);
				mi2.add_edge(n+i,n*3+j,1,1);
			}else if(mf[i][j]==1 && fm[j][i]==1){
				mi.add_edge(n+i,n*3+m+j,1,-1);
				mi2.add_edge(n+i,n*3+m+j,1,1000);
			}
		}
	}
	for(int i=0;i<n;i++){
		mi.add_edge(S,n*2+i,1,0);
		mi.add_edge(n*2+i,i,1,0);
		mi.add_edge(n*2+i,n+i,1,0);
		mi2.add_edge(S,n*2+i,1,0);
		mi2.add_edge(n*2+i,i,1,0);
		mi2.add_edge(n*2+i,n+i,1,0);
	}
	for(int i=0;i<m;i++){
		mi.add_edge(n*3+m*2+i,T,1,0);
		mi.add_edge(n*3+i,n*3+m*2+i,1,0);
		mi.add_edge(n*3+m+i,n*3+m*2+i,1,0);
		mi2.add_edge(n*3+m*2+i,T,1,0);
		mi2.add_edge(n*3+i,n*3+m*2+i,1,0);
		mi2.add_edge(n*3+m+i,n*3+m*2+i,1,0);
	}
	while(1){
		int val=mi.min_cost_flow(S,T,1,T+1);
		//printf("val%d\n",val);
		if(val>=0)break;
		if(val==-1000000){
			ans[0]++;
		}else if(val==-1000){
			ans[1]++;
		}else if(val==-1){
			ans[2]++;
		}
	}
	/*
	while(1){
		int val=mi2.min_cost_flow(S,T,1,T+1);
		printf("val%d\n",val);
		if(val==-1)break;
		if(val==1000){
			ans[2]++;
		}
	}
	*/
	printf("%d %d %d\n",ans[0],ans[1],ans[2]);
	return 0;
}



Measured memory_bytes: 3508