// /*
// */
// #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);
// void 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];
// }
// void 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]){
// flow[parent[node]][node] += minValOnPath;
// flow[node][parent[node]] -= minValOnPath;
// }
// }
// }
// out << maxFlow << '\n';
// for(int i = 1; i <= nrLeft; ++ i) {
// for(auto rNode : adj[i]){
// if(rNode == s)
// continue;
// if(capacity[i][rNode] == flow[i][rNode] == 1)
// out << i << ' ' << rNode - nrLeft << '\n';
// }
// }
// }
// 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);
// network.findMatching(0, n + m + 1);
// return 0;
// }
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
const char iname[] = "cuplaj.in";
const char oname[] = "cuplaj.out";
#define MAXN 20005
#define FOR(i, a, b) for (int i = (int)(a); i <= (int)(b); ++ i)
struct list {
int node, cap, flow;
list *nxt, *dup;
} ;
typedef list* plist;
plist adj[MAXN], edge[MAXN]; int n, m, q[MAXN], sel[MAXN], src, sink;
void alloc_edge(plist &nou, plist &dup, int i, int j)
{
nou = new list, dup = new list;
nou->node = j, dup->node = i;
nou->dup = dup, dup->dup = nou;
nou->nxt = adj[i], dup->nxt = adj[j];
adj[i] = nou, adj[j] = dup;
}
void read_in(void)
{
FILE *fi = fopen(iname, "r");
int cnt_edges, x, y;
plist nou, dup;
fscanf(fi, "%d %d %d", &n, &m, &cnt_edges);
for (; cnt_edges --; )
{
fscanf(fi, "%d %d", &x, &y);
alloc_edge(nou, dup, x, y + n);
nou->cap = 1, nou->flow = dup->cap = dup->flow = 0;
}
fclose(fi);
src = 0;
FOR (i, 1, n) {
alloc_edge(nou, dup, src, i);
nou->cap = 1, nou->flow = dup->cap = dup->flow = 0;
}
sink = n+m+1;
FOR (i, n + 1, n + m) {
alloc_edge(nou, dup, i, sink);
nou->cap = 1, nou->flow = dup->cap = dup->flow = 0;
}
}
int BFS(const int src, const int sink)
{
int h, t;
plist it;
memset(sel, 0, sizeof(sel));
edge[src] = 0;
for (sel[q[h = t = 0] = src] = 1; h <= t; ++ h)
{
for (it = adj[q[h]]; it; it = it->nxt)
if ((it->cap - it->flow) > 0 && !sel[it->node])
{
sel[q[++ t] = it->node] = 1;
edge[it->node] = it;
if (it->node == sink)
{
for (it = edge[sink]; it; it = edge[it->dup->node])
it->flow ++, it->dup->flow --;
return 1;
}
}
}
return 0;
}
int main(void)
{
read_in();
int cuplaj = 0;
while (BFS(src, sink)) cuplaj ++;
FILE *fo = fopen(oname, "w");
fprintf(fo, "%d\n", cuplaj);
FOR (i, 1, n)
{
for (plist it = adj[i]; it; it = it->nxt)
if (it->flow == 1)
fprintf(fo, "%d %d\n", i, it->node - n);
}
fclose(fo);
return 0;
}