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

// Template Headers {{{
using pii = pair<int, int>; using vpii = vector<pii>;
using vi = vector<int>; using vvi = vector<vi>;
using ll = long long; using vll = vector<long long>;
template <class T> using min_queue = priority_queue<T, vector<T>, greater<T>>;
template <class T> istream &operator>>(istream &, vector<T> &);
template <class T> ostream &operator<<(ostream &, const vector<T> &);
template <class T, class U> istream &operator>>(istream &, pair<T, U> &);
template <class T, class U> ostream &operator<<(ostream &, const pair<T, U> &);
template <class T> struct Inf { static constexpr T inf() { return std::numeric_limits<T>::has_infinity() ? std::numeric_limits<T>::infinty() : std::numeric_limits<T>::max(); } };
template <> struct Inf<int> { static constexpr int inf() { return 0x3f3f3f3f; } };
template <> struct Inf<long long> { static constexpr long long inf() { return 0x3f3f3f3f3f3f3f3fLL; } };
constexpr int INF = Inf<int>::inf(); constexpr ll BINF = Inf<ll>::inf();
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// }}}
// Dinic Maximum Flow {{{
template <class T>
class Dinic {

private:

	struct edge {
		int from, to; T cap;
		edge *rev;
		edge(int u, int v, T c) : from(u), to(v), cap(c), rev(nullptr) {}
	};

	static constexpr T INF = Inf<T>::inf();
	static constexpr int DINF = Inf<int>::inf();

	int n, s, t;
	std::vector<std::vector<edge*>> g;

public:

	Dinic(int n, int s, int t) : n(n), s(s), t(t), g(n) {}
	~Dinic() { for (auto v : g) for (edge *e : v) delete e; }

	void addEdge(int u, int v, T c) {
		edge *in = new edge(u, v, c);
		edge *out = new edge(v, u, 0);
		g[u].push_back(in); g[v].push_back(out);
		in->rev = out; out->rev = in;
	}

	T maxFlow() {
		T mxf = 0;
		std::vector<int> dist(n, DINF), vis(n);
		std::function<T(int, T)> dfs = [&] (int u, T fo) -> T {
			if (u == t) return fo;
			for (;vis[u]<int(g[u].size());vis[u]++) {
				edge *e = g[u][vis[u]];
				int v = e->to;
				if (dist[v] != dist[u] + 1 || e->cap <= 0) continue;
				T foo = dfs(v, std::min(fo, e->cap));
				if (foo > 0) {
					e->cap -= foo;
					e->rev->cap += foo;
					return foo;
				}
			}
			return 0;
		};
		for (;;) {
			for (int i=0;i<n;i++) dist[i] = DINF, vis[i] = 0;
			std::queue<int> q; q.push(s); dist[s] = 0;
			while (!q.empty()) {
				int u = q.front(); q.pop();
				if (u == t) break;
				for (edge *e: g[u]) {
					int v = e->to;
					if (e->cap > 0 && dist[v] == DINF) {
						dist[v] = dist[u] + 1;
						q.push(v);
					}
				}
			}
			if (dist[t] == DINF) break;
			while (T fo = dfs(s, INF))
				mxf += fo;
		}
		return mxf;
	}

};
template <class T> constexpr T Dinic<T>::INF;
template <class T> constexpr int Dinic<T>::DINF;
// }}}

int solve() {
	int n1, n2, m;
	cin >> n1 >> n2 >> m;
	Dinic<int> g(n1 + n2 + 2, n1 + n2, n1 + n2 + 1);
	for (int i=0;i<m;i++) {
		int u, v; cin >> u >> v;
		g.addEdge(u, n1 + v, 1);
	}
	for (int i=0;i<n1;i++) g.addEdge(n1 + n2, i, 1);
	for (int i=0;i<n2;i++) g.addEdge(n1 + i, n1 + n2 + 1, 1);
	cout << g.maxFlow() << endl;
	return 0;
}

// Template Main {{{
int main() {
	ios::sync_with_stdio(0);
	// precompute();
	// int t; cin >> t; for (int i=1;i<=t;i++)
	solve();
	// cout << "Case #" << i << ": ", solve();
	return 0;
}

template <class T> istream &operator>>(istream &is, vector<T> &v) {
	for (auto it=v.begin();it!=v.end();++it) is >> *it;
	return is;
}

template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
	for (auto it=v.begin();it!=v.end();) os << *it, os << " \n"[++it==v.end()];
	return os;
}

template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
	return is >> p.first >> p.second;
}

template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) {
	return os << p.first << ' ' << p.second;
}
// }}}

// vim: fdm=marker


Measured memory_bytes: 3868