#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;

int a[401][401];

void solve(){
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= m; ++j) cin >> a[i][j];
	
	unordered_set <int> del[401], ins[401];
	for (int i = 1; i <= n; ++i){
		unordered_set <int> s;
		for (int j = 1; j <= m; ++j){
			if (s.count(a[i][j])){
				del[a[i][j]].insert((i - 1) * m + j);
			}
			else s.insert(a[i][j]);
		}
		for (int j = 1; j <= m; ++j)
			if (!s.count(j)) ins[i].insert(j);
	}
	
	int cell = n * m + 1, cnt = 0;
	//vector <pii> ans;
	for (int i = 1; i <= m; ++i) cnt += del[i].size();
	if (cnt == 0){
		cout << 0;
		return;
	}
	cout << cnt + 1 << '\n';
	for (int i = 1; i <= m; ++i)
		if (!del[i].empty()){
			cell = *del[i].begin();
			//ans.pb({cell, m * n + 1});
			cout << cell << " " << m * n + 1 << '\n';
			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 = *ins[r].begin();
		if (del[color].empty()) color = *(++ins[r].begin());
		if (color == -1) exit(-1);
		int v = *del[color].begin(); del[color].erase(del[color].begin());
		//ans.pb({v, cell});
		cout << v << " " << cell << '\n';
		cell = v;
		ins[r].erase(color);
		--cnt;
	}
	//ans.pb({m * n + 1, cell});
	cout << 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();
}