#include <fstream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int NMAX = 20010;
const int EMAX = 200010;
struct Edge {
int to, cap, flow, rev;
};
vector<Edge> G[NMAX];
int vis[NMAX], p_node[NMAX], p_edge[NMAX];
int n, m, e;
void addEdge(int from, int to, int cap) {
G[from].push_back({to, cap, 0, (int)G[to].size()});
G[to].push_back({from, 0, 0, (int)G[from].size() - 1});
}
int bfs(int s, int d) {
memset(vis, 0, sizeof(vis));
memset(p_node, -1, sizeof(p_node));
queue<int> q;
q.push(s);
vis[s] = 1;
while(!q.empty()) {
int nod = q.front();
q.pop();
for(int i = 0; i < (int)G[nod].size(); i++) {
Edge &ed = G[nod][i];
if(!vis[ed.to] && ed.cap - ed.flow > 0) {
vis[ed.to] = 1;
q.push(ed.to);
p_node[ed.to] = nod;
p_edge[ed.to] = i;
}
}
}
if(!vis[d]) return 0;
int flow = 1e9;
int curr = d;
while(curr != s) {
int prev = p_node[curr];
int edge_idx = p_edge[curr];
flow = min(flow, G[prev][edge_idx].cap - G[prev][edge_idx].flow);
curr = prev;
}
curr = d;
while(curr != s) {
int prev = p_node[curr];
int edge_idx = p_edge[curr];
G[prev][edge_idx].flow += flow;
G[curr][G[prev][edge_idx].rev].flow -= flow;
curr = prev;
}
return flow;
}
int main() {
ifstream cin("cuplaj.in");
ofstream cout("cuplaj.out");
cin >> n >> m >> e;
int sursa = 0;
int dest = n + m + 1;
for(int i = 1; i <= n; i++) {
addEdge(sursa, i, 1);
}
for(int i = 1; i <= m; i++) {
int nod_r = n + i;
addEdge(nod_r, dest, 1);
}
for(int i = 0; i < e; i++) {
int u, v;
cin >> u >> v;
int nod_r = n + v;
addEdge(u, nod_r, 1);
}
int maxflow = 0;
int flow;
while((flow = bfs(sursa, dest)) > 0) {
maxflow += flow;
}
cout << maxflow << "\n";
for(int i = 1; i <= n; i++) {
for(auto &ed : G[i]) {
if(ed.to > n && ed.to <= n + m && ed.flow == 1) {
cout << i << " " << (ed.to - n) << "\n";
}
}
}
return 0;
}