#pragma GCC optimize "O3"

#include <bits/stdc++.h>

using namespace std;

constexpr int N = 1e4 + 10, INF = INT_MAX / 4;

class BipartiteMatching { // O( ( V + E ) * sqrt( V ) )
 public: 
  vector< int > G[ N ]; // N = total number of nodes = n + m
  int n, m, match[ N ], dist[ N ];
  // n: number of nodes on left side, nodes are numbered 1 to n
  // m: number of nodes on right side, nodes are numbered n+1 to n+m
  // G = NIL[0] ??? G1[G[1---n]] ??? G2[G[n+1---n+m]]
  bool BFS() {
    queue< int > Q;
    for (int i = 1; i <= n; i++ ) {
      if ( match[ i ] == 0 ) {
        dist[ i ] = 0;
        Q.push( i );
      }
      else dist[ i ] = INF;
    }
    dist[ 0 ] = INF;
    while ( !Q.empty() ) {
      int u = Q.front(); Q.pop();
      if ( u != 0 )
        for(int v : G[u])
          if ( dist[ match[ v ] ] == INF ) {
            dist[ match[ v ] ] = dist[ u ] + 1;
            Q.push( match[ v ] );
          }
    }
    return ( dist[ 0 ] != INF );
  }
  bool DFS( int u ) {
    if ( u != 0 ) {
      for(int v : G[u])
        if ( dist[ match[ v ] ] == dist[ u ] + 1 and DFS( match[ v ] ) ) {
          match[ v ] = u;
          match[ u ] = v;
          return true;
        }
      dist[ u ] = INF;
      return false;
    }
    return true;
  }
  int Solve() {
    int matching = 0;
    fill_n(match, n+m+1, 0);
    while ( BFS() )
      for (int i = 1; i <= n; i++ )
        if ( match[ i ] == 0 and DFS( i ) ) matching++;
    return matching;
  }
  void AddEdge( int u, int v ) { G[ u ].push_back( n + v ); }
} ob;

int main() {
  int E; scanf("%d %d %d", &ob.n, &ob.m, &E);
  for(int i = 0; i < E; ++i) {
    int x, y; scanf("%d %d", &x, &y);
    ob.AddEdge(x+1, y+1);
  }
  printf("%d\n", ob.Solve());
}