#include <bits/stdc++.h>
using namespace std;
const int N=55;
const int M=405;
const int MN=830000;
int l[MN],r[MN],cnt[N],a[N][M],t,ans1,m,n,p[N];
int color_count[N][N];
void move(int x,int y){
if(cnt[x] <= 0) return;
if(ans1 >= MN-1) return;
int color = a[x][cnt[x]];
color_count[x][color]--;
color_count[y][color]++;
++ans1;
l[ans1]=x;
r[ans1]=y;
a[y][++cnt[y]]=a[x][cnt[x]--];
}
inline int count(int x,int y){
return color_count[x][y];
}
inline int top(int x){
if(cnt[x] <= 0) return 0;
return a[x][cnt[x]];
}
void move_all_color(int x, int y, int target) {
stack<int> temp;
while(cnt[x] > 0) {
if(top(x) == target) {
move(x, y);
} else {
temp.push(top(x));
move(x, n+1);
}
}
while(!temp.empty()) {
move(n+1, x);
temp.pop();
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin>>n>>m;
memset(color_count, 0, sizeof(color_count));
for(int i=1;i<=n;i++){
cnt[i]=m;
for(int j=1;j<=m;j++){
cin>>a[i][j];
color_count[i][a[i][j]]++;
}
}
cnt[n+1]=0;
for(int i=1;i<=n+1;i++) p[i]=i;
for(int now=n;now>=3;now--){
move_all_color(p[1], p[now], now);
while(count(p[2], now) > 0) {
if(cnt[p[1]] < m) {
move(p[2], p[1]);
} else {
move(p[2], p[now+1]);
}
}
swap(p[1], p[now]);
swap(p[2], p[now+1]);
for(int k=1;k<now;k++){
move_all_color(p[k], p[now], now);
swap(p[k], p[now]);
swap(p[k], p[now+1]);
}
for(int i=1;i<now;i++) {
while(top(p[i]) == now) {
move(p[i], p[now+1]);
}
}
for(int i=1;i<now;i++) {
while(cnt[p[i]] < m && cnt[p[now]] > 0) {
move(p[now], p[i]);
}
}
}
t=count(p[1],1);
for(int i=1;i<=t;i++) move(p[2],p[3]);
for(int i=1;i<=m;i++) {
if(top(p[1])==1) move(p[1],p[2]);
else move(p[1],p[3]);
}
for(int i=1;i<=t;i++) move(p[2],p[1]);
for(int i=1;i<=m-t;i++) move(p[3],p[1]);
while(cnt[p[3]]) move(p[3],p[2]);
for(int i=1;i<=m-t;i++) move(p[1],p[3]);
for(int i=1;i<=m;i++) {
if(top(p[2])==1) move(p[2],p[1]);
else move(p[2],p[3]);
}
cout<<ans1<<endl;
for(int i=1;i<=ans1;i++){
cout<<l[i]<<" "<<r[i]<<endl;
}
return 0;
}