#include <cstdio>
#include <vector>
#include <bitset>
using namespace std;
vector<vector<int>> Graph; // Graph[i] = the neighbours of i on the right (i being on the left)
vector<int> Left; // Left[i] = who's i's match on the left (i being on the right)
vector<int> Right; // Right[i] = who's i's match on the right (i being on the left)
bitset<10005> used; // used[i] = true <=> i is part of an alternating path in the current run
bool findMatch(int k)
{
if (used[k])
return false; // k was already part of an alternating path in this run
used[k] = true;
for (auto v : Graph[k])
if (Left[v] == -1) {
Right[k] = v;
Left[v] = k;
return true;
}
/**
There is no free neighbour for k, but if we can find a match
for the Left[v] which is not v, without touching the alternating
path that we are building, then we can link k to v.
*/
for (auto v: Graph[k])
if (findMatch(Left[v])) {
Right[k] = v;
Left[v] = k;
return true;
}
// We failed to extend the alternating path.
return false;
}
int main()
{
freopen("cuplaj.in", "r", stdin);
freopen("cuplaj.out", "w", stdout);
int L, R, M;
scanf("%d%d%d", &L, &R, &M);
Graph.resize(L);
Left.resize(R);
Right.resize(L);
fill(Left.begin(), Left.end(), -1);
fill(Right.begin(), Right.end(), -1);
for (int i = 0; i < M; ++i) {
int l, r;
scanf("%d%d", &l, &r);
--l;
--r;
Graph[l].emplace_back(r);
}
/**
Every pair in the maximal match has a node on the left side. Thus,
we equivalently try to maximize the number of nodes on the left that
are part of a match using alternating paths.
*/
int matches = 0;
bool madeProgress = true;
while (madeProgress) {
madeProgress = false;
used = 0;
/**
For each node that does not have a match already, we try to find it match.
If successful, then we increased the number nodes on the left that are
part of a match.
*/
for (int i = 0; i < L; ++i)
if (Right[i] == -1 && findMatch(i)) {
++matches;
madeProgress = true;
}
}
printf("%d\n", matches);
for (int i = 0; i < L; ++i)
if (Right[i] != -1)
printf("%d %d\n", i + 1, Right[i] + 1);
return 0;
}