#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned ll
#define ff first
#define ss second
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define pb push_back
#define pii pair <int, int>
using namespace std;
const ll inf = 1e18;
constexpr ll mod = 998244353;
const int MAXN = 1e5+10;

void solve(){
	int n, m;
	cin >> n >> m;
	vector < vector <int> > a(n+1, vector <int> (m+1));
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= m; ++j) cin >> a[i][j];
	
	map <int, set <int> > del, free;
	for (int i = 1; i <= n; ++i){
		set <int> s;
		for (int j = 1; j <= m; ++j){
			if (s.find(a[i][j]) != s.end()){
				del[a[i][j]].insert((i - 1) * m + j);
				//free[i].insert((i - 1) * m + j);
			}
			else s.insert(a[i][j]);
		}
	}
	
	map <int, set <int> > ins;
	for (int i = 1; i <= n; ++i){
		set <int> s;
		for (int j = 1; j <= m; ++j){
			s.insert(a[i][j]);
		}
		for (int j = 1; j <= m; ++j)
			if (s.find(j) == s.end()) ins[i].insert(j);
	}
	/*for (auto i : ins){
		cout << i.ff << " -> ";
		for (auto j : i.ss) cout << j << " ";
		cout << '\n';
	}*/
	
	if (del.empty()){
		cout << 0;
		return;
	}
	
	int cell = n * m + 1, cnt = 0;
	vector <pii> ans;
	for (int i = 1; i <= m; ++i) cnt += del[i].size();
	for (int i = 1; i <= m; ++i)
		if (!del[i].empty()){
			cell = *del[i].begin();
			ans.pb({cell, m * n + 1});
			del[i].erase(del[i].begin());
			//if (del[i].empty()) del.erase(i);
			--cnt;
			break;
		}
	while (cnt){
		int r = (cell + m - 1) / m;
		int color = -1;
		for (auto i : ins[r]){
			color = i;
			if (!del[color].empty()) break;
		}
		if (color == -1) exit(-1);
		int v = *del[color].begin(); del[color].erase(del[color].begin());
		ans.pb({v, cell});
		cell = v;
		ins[r].erase(color);
		--cnt;
	}
	ans.pb({m * n + 1, cell});
	cout << ans.size() << '\n';
	for (auto i : ans) cout << i.ff << " " << i.ss << '\n';
}
 
signed main(){
    ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    solve();
}