#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a, b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define DBG printf("this is a input\n")
#define first fi
#define second se
#define mk(a, b) make_pair(a,b)
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a, ll b) {
return a / gcd(a, b) * b;
}
int head[1000000],cnt=0;
struct e
{
int to;
int next;
int c;
}edge[3000000];
void add(int f , int t , int c)
{
edge[cnt].to = t;
edge[cnt].next = head[f];
edge[cnt].c = c;
head[f] = cnt ++;
}
int n , m , k, st ,ed;
int level[1000000] , cur[1000000];
bool dinicBfs(int s, int e)
{
mem(level,0);
queue<int>q;
q.push(s);
level[s] = 1;
while(!q.empty())
{
int root = q.front();
q.pop();
for(int i = head[root] ; i != -1; i = edge[i].next)
{
int v = edge[i].to , c = edge[i].c;
if(level[v] == 0 && c > 0)
{
level[v] = level[root]+1;
q.push(v);
}
}
}
return level[e] != 0;
}
int dinicDfs(int root ,int flow)
{
if(root == ed)
return flow;
int newflow;
for(int& i = cur[root] ; i != -1 ; i = edge[i].next)
{
int v = edge[i].to , c = edge[i].c;
if(c > 0 && level[v] == level[root]+1 && (newflow = dinicDfs(v,min(c,flow))))
{
edge[i].c -= newflow;
edge[i^1].c += newflow;
return newflow;
}
}
return 0;
}
int dinic()
{
int ans = 0;
while(dinicBfs(st, ed))
{
for(int i = 0 ; i <= n+m+1 ; i ++)
cur[i] = head[i];
while(int crease = dinicDfs(st,INF))
ans += crease;
}
return ans;
}
int main(void)
{
mem(head,-1);
cin>>n>>m>>k;
st = 0;
ed = n+m+1;
for(int i = 1 ; i <= k ; i ++)
{
int u , v;
cin>>u>>v;
if(u <= n && v <= m) {
add(u, v+n,1);
add(v+n,u,0);
}
}
for(int i = 1 ; i <= n ; i++)
add(st,i,1),add(i,st,0);
for(int i = 1 ; i <= m ; i ++)
add(i+n,ed,1),add(ed,i+n,0);
int ans = dinic();
cout<<ans<<endl;
}