#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <limits.h>
using namespace std;
int n,m,e;
//the pairs of set U (values are the nodes from set V)
int pair1[10001];
//the pairs of set V (values are nodes from U)
int pair2[10001];
int dist[10001];
vector<int> adjacencyList[10001];
int bfs(){
queue<int> q;
for (int i=1; i<=n; i++){
// if its a free node
if (pair1[i] == 0){
q.push(i);
dist[i] = 0;
} else {
dist[i] = -1;
}
}
int foundLengthOfMinAugmentedTree = INT_MAX;
while (!q.empty()){
int currentNode = q.front();
q.pop();
if (foundLengthOfMinAugmentedTree > dist[currentNode]){
for (int i=0; i<adjacencyList[currentNode].size(); i++){
int v = adjacencyList[currentNode][i];
if (pair2[v] == 0){
foundLengthOfMinAugmentedTree = dist[currentNode] + 1;
} else {
//if not seen yet
if (dist[pair2[v]] == -1){
dist[pair2[v]] = dist[currentNode] + 1;
q.push(pair2[v]);
}
}
}
}
}
return foundLengthOfMinAugmentedTree != INT_MAX; // meaning that there is an augmented tree
}
int dfs(int currentNode){
for (int i=0; i<adjacencyList[currentNode].size(); i++){
int v = adjacencyList[currentNode][i];
if (pair2[v] == 0){
pair2[v] = currentNode;
pair1[currentNode] = v;
return 1;
}
else if (dist[pair2[v]] == dist[currentNode]+1){
if (dfs(pair2[v])){
pair2[v] = currentNode;
pair1[currentNode] = v;
return 1;
}
}
}
return 0;
}
int main()
{
freopen("cuplaj.in", "r", stdin);
freopen("cuplaj.out", "w", stdout);
scanf("%d %d %d", &n, &m, &e);
int u,v;
for (int i=0; i<e; i++){
scanf("%d %d", &u, &v);
adjacencyList[u].push_back(v);
}
int couplingsNr = 0;
while (bfs()){
for (int i=1; i<=n; i++){
if (pair1[i] == 0){
// it is a free vertex and we try to find out if it leads to an augmenting path
if (dfs(i)){
couplingsNr++;
}
}
}
}
printf("%d\n", couplingsNr);
for (int i=1; i<=n; i++){
if (pair1[i] != 0){
printf("%d %d\n", i, pair1[i]);
}
}
return 0;
}