#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ar array
#define vt vector
#define pq priority_queue
#define pu push
#define pub push_back
#define em emplace
#define emb emplace_back
#define all(x) x.begin(), x.end()
#define allr(x) x.rbegin(), x.rend()
#define allp(x, l, r) x.begin() + l, x.begin() + r
#define len(x) (int)x.size()
using namespace std;
using namespace __gnu_pbds;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
template <class T, size_t N>
void re(array <T, N>& x);
template <class T>
void re(vt <T>& x);
template <class T>
void re(T& x) {
cin >> x;
}
template <class T, class... M>
void re(T& x, M&... args) {
re(x); re(args...);
}
template <class T>
void re(vt <T>& x) {
for(auto& it : x)
re(it);
}
template <class T, size_t N>
void re(array <T, N>& x) {
for(auto& it : x)
re(it);
}
template <class T, size_t N>
void wr(array <T, N> x);
template <class T>
void wr(vt <T> x);
template <class T>
void wr(T x) {
cout << x;
}
template <class T, class ...M> void wr(T x, M... args) {
wr(x), wr(args...);
}
template <class T>
void wr(vt <T> x) {
for(auto it : x)
wr(it, ' ');
}
template <class T, size_t N>
void wr(array <T, N> x) {
for(auto it : x)
wr(it, ' ');
}
inline void Open(const string Name) {
#ifndef ONLINE_JUDGE
(void)!freopen((Name + ".in").c_str(), "r", stdin);
(void)!freopen((Name + ".out").c_str(), "w", stdout);
#endif
}
struct HopcroftKarp {
int n;
vt <int> l, r;
vt <bool> vis;
vt <vt <int>> adj;
HopcroftKarp() {}
HopcroftKarp(int _n, int _m) {
n = _n;
adj.resize(n);
vis.resize(n, false);
l.resize(n, -1);
r.resize(_m, -1);
}
void init(int _n, int _m) {
n = _n;
adj.resize(n);
vis.resize(n, false);
l.resize(n, -1);
r.resize(_m, -1);
}
void add_edge(int u, int v) {
adj[u].emb(v);
}
bool pairup(int u, int depth) {
/* if we already visited the node before it means we already tried all options for it */
if (vis[u]) {
return false;
}
/* if for an edge we can have a pair we make the pair */
vis[u] = true;
for (int v : adj[u]) {
if (r[v] == -1) {
l[u] = v;
r[v] = u;
return true;
}
}
/* if for the u' edge that pairs with v, we have another match
then we can make a match with u and v
*/
for (int v : adj[u]) {
if (r[v] != -1 and pairup(r[v], depth + 1)) {
l[u] = v;
r[v] = u;
return true;
}
}
return false;
}
int maximum_matching() {
int ans = 0;
/* we repeat the process till we cannot have any matches */
for (int change = 1; change; ) {
change = 0;
fill(all(vis), false);
for(int u = 0; u < n; u++) {
if(l[u] == -1) {
/* if we have one match we repeat the process again */
change |= pairup(u, 0);
}
}
}
for (int u = 0; u < n; ++u)
ans += (l[u] != -1);
return ans;
}
};
void solve() {
int n, m, e; re(n, m, e);
HopcroftKarp F(n, m);
for (int i = 0; i < e; ++i) {
int u, v; re(u, v);
--u, --v;
F.add_edge(u, v);
}
wr(F.maximum_matching(), '\n');
for (int i = 0; i < n; ++i)
if (F.l[i] != -1) {
wr(i + 1, ' ', F.l[i] + 1, '\n');
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
Open("cuplaj");
int t = 1;
for(;t;t--) {
solve();
}
return 0;
}