#include <vector>
#include <array>
#include <algorithm>
#include <iostream>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <map>
#include <math.h>
#include <assert.h>
#include <queue>
#include <deque>
#include <iomanip>
#include <numeric>
#include <fstream>

using namespace std;

typedef long long ll;
typedef long double ld;

#define fi first
#define se second

#define mp make_pair
#define pb push_back
#define sz(x) ((int)(x).size())

typedef vector<int> vi;
typedef vector<double> vd;
typedef vector<ld> vld;
typedef vector<vector<int>> vvi;
typedef vector<ll> vl;
typedef vector<vector<ll>> vvl;
typedef vector<vector<ld>> vvd;
typedef vector<string> vs;
typedef vector<bool> vb;

typedef pair <int, int> pii;
typedef pair <ll, ll> pll;

const ll MAXN = 101;
ll n, m;
ll pole[MAXN][MAXN];
ll pole2[MAXN][MAXN];
ll pole3[MAXN][MAXN];

struct Kek {
    Kek(ll n, const vvl& g) : n(n), k(n), g(g) {
        mt.assign (k, -1);
        for (int v=0; v<n; ++v) {
            used.assign (n, false);
            try_kuhn (v);
        }
    }

    vector<pll> get() {
        vector<pll> ans;
        for (int i=0; i<k; ++i) {
            if (mt[i] != -1) ans.emplace_back(mt[i], i);
        }
        assert(ans.size() == n);
        return ans;
    }

    bool try_kuhn (int v) {
        if (used[v])  return false;
        used[v] = true;
        for (size_t i=0; i<g[v].size(); ++i) {
            int to = g[v][i];
            if (mt[to] == -1 || try_kuhn (mt[to])) {
                mt[to] = v;
                return true;
            }
        }
        return false;
    }

    int n, k;
    vvl g;
    vector<int> mt;
    vector<char> used;
};

vvl g(MAXN);

int main() {
    cout << setprecision(30);
    ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);

    cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            cin >> pole[i][j];
            --pole[i][j];
            g[i].pb(pole[i][j] / m);
        }
    }

    for (int i = 0; i < m; ++i) {
        Kek kek = Kek(n, g);
        auto match = kek.get();
        for (int k = 0; k < n; ++k) {
            ll v = match[k].fi;
            ll u = match[k].se;

            for (auto it = g[v].begin(); it != g[v].end(); ++it) {
                if (*it == u) {
                    g[v].erase(it);
                    break;
                }
            }

            for (int y = 0; y < m; ++y) {
                ll val = pole[v][y];
                if (val / m == u) {
                    pole[v][y] = -m -m;
                    pole2[v][i] = val;
                    break;
                }
            }
            
            // cerr << v << " " << u << endl;
        }

        // cerr << endl;
    }

    for (int x = 0; x < n; ++x) {
        for (int y = 0; y < m; ++y) {
            cout << (pole2[x][y] + 1) << " ";
        }
        cout << "\n";
    }

    for (int y = 0; y < m; ++y) {
        vl lol(n);
        for (int x = 0; x < n; ++x) {
            lol[x] = pole2[x][y];
        }
        sort(lol.begin(), lol.end());
        for (int x = 0; x < n; ++x) {
            pole3[x][y] = lol[x];
        }
    }

    for (int x = 0; x < n; ++x) {
        for (int y = 0; y < m; ++y) {
            cout << (pole3[x][y] + 1) << " ";
        }
        cout << "\n";
    }

    return 0;
}


Measured memory_bytes: 768