#include <bits/stdc++.h>

#define ll long long
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define watch(x) cout << (#x) << " : " << x << '\n'
#define boost ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

using namespace std;

vector < vector<int> > a;
int n, m;

int conv(int i, int j) {
    return i * m + j + 1;
}

// p[i][j][0] = {i, j} -> have
// p[i][j][1] = {i, j} -> need

//vector < vector < vector < int > > >  p;

// maybe map[x] -> all pos, where x odd in map[x][0] = {i, j}
vector < pair < pair<int, int>, pair<int, int> > > ans;
map <int, vector < pair<int, int> > > mp;
vector < vector<int> > there;

void go(int f1, int f2, int t1, int t2) {
    ans.push_back({{f1, f2}, {t1, t2}});
}

void init() {
    there.resize(n, vector<int>(m));
    for (int i = 0; i < n; i++) {
        vector <int> p(m+1);
        for (int j = 0; j < m; j++)
            p[a[i][j]]++;
        vector <int> need;
        for (int j = 1; j <= m; j++)
            if (!p[j])
                need.push_back(j);
        for (int j = 0; j < m; j++)
            if (p[a[i][j]] > 1) {
                mp[a[i][j]].push_back({i, j});
                p[a[i][j]]--;
                there[i][j] = need.back(); need.pop_back();
            }
    }
}

bool nice() {
    int cnt = 0;
    for (auto c : there)
        cnt += accumulate(all(c), 0);
    return !cnt;
}

int Try(int val, int pos) {
    int ansSize = 1;
    auto copyMap = mp;
    auto copyThere = there;
    int curI = n, curJ = 0;
    swap(copyMap[val][pos].first, curI);
    swap(copyMap[val][pos].second, curJ);
    while (true) {
        if (curI == n && curJ == 0)
            break;
        int needTo = copyThere[curI][curJ];
        copyThere[curI][curJ] = 0;
        ansSize++;
        curI = copyMap[needTo].back().first;
        curJ = copyMap[needTo].back().second;
        copyMap[needTo].pop_back();
    }
    return ansSize;
}

void solve() {
    cin >> n >> m;
    a.resize(n, vector<int>(m));
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> a[i][j];
    init();

    while (!nice()) {
        int curI = n, curJ = 0;
        pair < int, pair<int, int> > where;
        for (int j = 1; j <= m; j++) {
            for (int k = 0; k < mp[j].size(); k++) {
                int t = Try(j, k);
                if (t > where.first)
                    where = {t, {j, k}};
            }
        }

        go(mp[where.second.first][where.second.second].first, curI, mp[where.second.first][where.second.second].second, curJ);
        swap(mp[where.second.first][where.second.second].first, curI);
        swap(mp[where.second.first][where.second.second].second, curJ);

        while (true) {
            if (curI == n && curJ == 0)
                break;
            int needTo = there[curI][curJ];
            there[curI][curJ] = 0;
            go(mp[needTo].back().first, mp[needTo].back().second, curI, curJ);
            curI = mp[needTo].back().first;
            curJ = mp[needTo].back().second;
            mp[needTo].pop_back();
        }
    }

    cout << (int) ans.size() << '\n';
    for (auto [l, r] : ans)
        cout << conv(l.first, l.second) << ' ' << conv(r.first, r.second) << '\n';
}

/*
swap 1 2 3 3
swap 2 3 3 2
swap 1 2 5 2
swap 4 3 5 3
*/

main () {
//    boost;
    solve();
    return 0;
}
