#include <stdio.h>
#include <map>
#include <vector>
#include <queue>
#include <limits.h>
using namespace std;
typedef map<int, int> edge;
typedef vector<map<int, int>> edges;
edges graph;
int L, R, V, E;
FILE* fin, * fout;
bool edgeExists(edges &graph,int u,int v) {
edge e = graph[u];
return (e.find(v) != e.end());
}
bool bfs(edges graph, int source, int sink, vector<int>& parent) {
queue<int> q;
q.push(source);
vector<bool> viz(V + 1, false);
viz[source] = true;
parent[source] = -1;
while (!q.empty()) {
int u = q.front();
q.pop();
if (u == sink)
return true;
for (auto e : graph[u]) {
int v = e.first, capacity = e.second;
if (viz[v] == false && capacity > 0) {
q.push(v);
viz[v] = true;
parent[v] = u;
}
}
}
return false;
}
void maximumMatching(edges graph, int V, int source, int sink) {
edges residualGraph(V + 1);
for (int u = 0;u <= V;++u) {
for (auto e : graph[u]) {
int v = e.first, capacity = e.second;
residualGraph[u][v] = capacity;
if (!edgeExists(residualGraph,v,u))
residualGraph[v][u] = 0;
}
}
edges resultGraph(V + 1);
int max_flow = 0;
vector<int> parent(V + 1, -1);
while (bfs(residualGraph, source, sink, parent)) {
int flow = 1;
for (int v = sink;v != source;v = parent[v]) {
int u = parent[v];
residualGraph[u][v] -= flow;
residualGraph[v][u] += flow;
}
max_flow += flow;
}
for (int u = 0;u <= V;++u) {
for (auto e : graph[u]) {
int v = e.first, capacity = e.second;
resultGraph[u][v] = max(0, capacity - residualGraph[u][v]);
}
}
fprintf(fout, "%i\n", max_flow);
for (int u = 1;u <= L;++u) {
for (auto e : resultGraph[u]) {
int v = e.first, flow = e.second;
if (flow > 0)
fprintf(fout, "%i %i\n", u, v - L);
}
}
}
int main() {
fin = fopen("cuplaj.in", "r");
fout = fopen("cuplaj.out", "w");
fscanf(fin, "%i %i %i", &L, &R, &E);
V = L + R + 1;
graph.resize(V + 1);
for (int e = 1;e <= E;++e) {
int x, y;
fscanf(fin, "%i %i", &x, &y);
graph[x][y + L] = 1;
}
for (int i = 1;i <= L;++i)
graph[0][i] = 1;
for (int i = L + 1;i <= L + R;++i)
graph[i][V] = 1;
maximumMatching(graph, V, 0, V);
}