#include <bits/stdc++.h>
/*
#include <ext/rope>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_cxx;
using namespace __gnu_pbds;
*/

#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("avx,avx2,tune=native")

#define fast ios_base::sync_with_stdio(0); cin.tie(nullptr); cout.tie(nullptr);

#define CR const&

#define FORI(i, a, b) for(int i = a, max##i = b; i < max##i; ++i)
#define FOR(i, n) FORI(i, 0, n)
#define RFORI(i, a, b) for(int i = a, min##i = b; i >= min##i; --i)
#define RFOR(i, n) RFORI(i, n, 0)
#define FORA(i, a) for(auto i : a)
#define FORAR(i, a) for(auto& i : a)
#define FORACR(i, a) for(auto CR i : a)
#define ALL(obj) begin(obj), end(obj)
#define RALL(obj) rbegin(obj), rend(obj)
#define Count(q) while(q--)

#define OK cerr << "OK" << endl;

#define pb push_back


using namespace std;

template<class T>
using V = vector<T>;
template<class T>
using VV = V<V<T>>;

using ld = long double;
using ll = long long;
using PLL = pair<ll, ll>;
using PII = pair<int, int>;
using VI = V<int>;
using VLL = V<ll>;
using VVI = VV<int>;
using VVLL = VV<ll>;
using Gr = VVI;
using MLL = map<ll, ll>;

template<class T>
constexpr T sqr(T x)
{
    return x * x;
}

template<class T, class U = T>
void cmin(T& a, U const& b)
{
    if(b < a)
        a = b;
}

template<class T, class U = T>
void cmax(T& a, U const& b)
{
    if(a < b)
        a = b;
}

ll get_time()
{
    using namespace chrono;
    return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
}
mt19937 rng(get_time());

void DFS(int u, Gr& G, VI& path)
{
    while(!G[u].empty())
    {
        int v = G[u].back();
        G[u].pop_back();
        DFS(v, G, path);
    }

    path.pb(u);
}

int main()
{
    fast
    int n, m;
    cin >> n >> m;

    VI a(n * m);
    FORAR(i, a)
    {
        cin >> i;
        --i;
    }

    VV<VI> pos(n, VVI(m));

    FOR(i, n)
        FORI(j, i * m, (i + 1) * m)
            pos[i][a[j]].pb(j);

    Gr G(n + m);
    FOR(i, n)
        FOR(j, m)
        {
            if(pos[i][j].size() == 0)
                G[j + n].pb(i); //element j -> pos i
            else
                FOR(_, pos[i][j].size() - 1)
                    G[i].pb(j + n); //pos i -> element j
        }

    /*FOR(i, n + m)
    {
        cerr << i << " -> ";
        for(auto j : G[i])
            cerr << j << " ";
        cerr << "\n";
    }
    OK*/

    V<PII> ans;
    FOR(q, n) //pos i
    {
        if(G[q].empty())
            continue;

        VI path;
        DFS(q, G, path);
        reverse(ALL(path));

        /*cerr << q << " -> ";
        for(auto i : path)
            cerr << i << " ";
        cerr << "\n";*/

        int k = path.size();

        VI p{n * m};
        for(int i = 0; i < k - 1; i += 2)
        {
            p.pb(pos[path[i]][path[i + 1] - n].back());
            pos[path[i]][path[i + 1] - n].pop_back();
        }

        p.pb(n * m);
        /*cerr << "p: ";
        for(auto i : p)
            cerr << i << " ";
        cerr << "\n";*/
        reverse(ALL(p));
        FOR(i, p.size() - 1)
            ans.pb({p[i + 1], p[i]});
    }

    cout << ans.size() << "\n";
    FORACR(i, ans)
        cout << i.first + 1 << " " << i.second + 1 << "\n";
}
