#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
class Dinic {
private:
struct Edge {
int from, to, flow, cap;
};
int nodes, source, sink;
const int INF = (1 << 30);
vector <int> last, level;
vector <Edge> edges;
vector <vector <pair <int, int>>> graph;
bool bfs() {
fill(level.begin(), level.end(), INF);
level[source] = 0;
queue <int> q;
q.push(source);
while (!q.empty()) {
int node = q.front();
q.pop();
for (auto& it : graph[node]) {
int flow = edges[it.second].flow;
int cap = edges[it.second].cap;
if (flow < cap && level[it.first] > level[node] + 1) {
level[it.first] = level[node] + 1;
q.push(it.first);
}
}
}
return (level[sink] != INF);
}
int dfs(int node, int deltaFlow) {
if (node == sink || deltaFlow == 0) {
return deltaFlow;
}
else {
for (int& p = last[node]; p < graph[node].size(); ++p) {
int nextNode = graph[node][p].first;
int edgeId = graph[node][p].second;
int flow = edges[edgeId].flow;
int cap = edges[edgeId].cap;
if (level[nextNode] == level[node] + 1 && flow < cap) {
int pushed = dfs(nextNode, min(deltaFlow, cap - flow));
if (pushed) {
edges[edgeId].flow += pushed;
edges[edgeId ^ 1].flow -= pushed;
return pushed;
}
}
}
return 0;
}
}
public:
Dinic(int _nodes, int _source, int _sink) {
nodes = _nodes;
source = _source;
sink = _sink;
last.resize(nodes, 0);
level.resize(nodes, 0);
graph.resize(nodes, vector <pair <int, int>>());
}
void addEdge(int from, int to, int cap) {
Edge forward = { from, to, 0, cap };
Edge backward = { to, from, 0, 0 };
graph[from].push_back({ to, edges.size() });
edges.push_back(forward);
graph[to].push_back({ from, edges.size() });
edges.push_back(backward);
}
int maxFlow() {
int flow = 0;
while (bfs()) {
fill(last.begin(), last.end(), 0);
int deltaFlow = dfs(source, INF);
while (deltaFlow > 0) {
flow += deltaFlow;
deltaFlow = dfs(source, INF);
}
}
return flow;
}
vector <pair <int, int>> bipartiteMatching() {
vector <pair <int, int>> matching;
for (auto& it : edges) {
if (it.flow == 1 && it.flow == it.cap && it.from != source && it.to != sink) {
matching.push_back({ it.from, it.to });
}
}
return matching;
}
};
int main() {
ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");
int N, M, E;
fin >> N >> M >> E;
Dinic dinic(N + M + 2, 0, N + M + 1);
for (int i = 0; i < E; ++i) {
int u, v;
fin >> u >> v;
dinic.addEdge(u, v + N, 1);
}
for (int i = 1; i <= N; ++i) {
dinic.addEdge(0, i, 1);
}
for (int i = 1; i <= M; ++i) {
dinic.addEdge(i + N, N + M + 1, 1);
}
fout << dinic.maxFlow() << '\n';
auto answer = dinic.bipartiteMatching();
for (auto& it : dinic.bipartiteMatching()) {
fout << it.first << ' ' << it.second - N << '\n';
}
fin.close();
fout.close();
return 0;
}