/*
*/
#include <bits/stdc++.h>
using namespace std;
ifstream in("cuplaj.in");
ofstream out("cuplaj.out");
class Solution {
int n, m, nrLeft;
vector<vector<int>> capacity, flow, adj;
vector<bool> viz;
vector<int> parent;
public:
Solution(int _n, int _m, vector<tuple<int, int, int>> edges, int nrLeft);
bool bfs(int src);
pair<int, vector<pair<int, int>>> findMatching(int s, int t);
};
bool Solution::bfs(int src) {
fill(viz.begin(), viz.end(), false);
fill(parent.begin(), parent.end(), -1);
queue<int> q;
q.push(src);
viz[src] = true;
int currNode;
while(!q.empty()) {
currNode = q.front();
q.pop();
for(auto nextNode : adj[currNode])
if(!viz[nextNode] && capacity[currNode][nextNode] - flow[currNode][nextNode] > 0) {
viz[nextNode] = true;
if(nextNode != n) {
q.push(nextNode);
parent[nextNode] = currNode;
}
}
}
return viz[n];
}
pair<int, vector<pair<int, int>>> Solution::findMatching(int s, int t) {
int maxFlow = 0;
vector<pair<int, int>> matchingEdges;
while(bfs(s)) {
for(auto leaf : adj[t]) {
if(capacity[leaf][t] - flow[leaf][t] <= 0 || !viz[leaf])
continue;
parent[t] = leaf;
int minValOnPath = 110000;
for(int node = t; parent[node] != -1; node = parent[node])
minValOnPath = min(minValOnPath, capacity[parent[node]][node] - flow[parent[node]][node]);
if(!minValOnPath)
continue;
maxFlow += minValOnPath;
for(int node = t; parent[node] != -1; node = parent[node]) {
if(parent[node] != s && node != t)
matchingEdges.push_back({parent[node], node - nrLeft});
flow[parent[node]][node] += minValOnPath;
flow[node][parent[node]] -= minValOnPath;
}
}
}
return {maxFlow, matchingEdges};
}
Solution::Solution(int _n, int _m, vector<tuple<int, int, int>> edges, int nrLeft) {
n = _n;
m = _m;
this->nrLeft = nrLeft;
adj.resize(n + 1);
viz.resize(n + 1);
parent.resize(n + 1);
capacity.resize(n + 1, vector<int>(n + 1, 0));
flow.resize(n + 1, vector<int>(n + 1, 0));
int x, y, c;
for(auto& edge : edges) {
x = get<0>(edge); y = get<1>(edge); c = get<2>(edge);
capacity[x][y] = c;
adj[x].push_back(y);
adj[y].push_back(x);
}
}
int main() {
vector<tuple<int, int, int>> edges;
int n, m, x, y, e;
in >> n >> m >> e;
while(e --) {
in >> x >> y;
edges.push_back({0, x, 1});
edges.push_back({x, n + y, 1});
edges.push_back({n + y, n + m + 1, 1});
}
Solution network(n + m + 1, e, edges, n);
auto solution = network.findMatching(0, n + m + 1);
out << solution.first << '\n';
sort(solution.second.begin(), solution.second.end());
for(auto edge : solution.second)
out << edge.first << ' ' << edge.second << '\n';
return 0;
}