#include <functional>
#include <cstring>
#include <algorithm>
#include <cassert>
#include <set>
#include <vector>
#include <iostream>
using namespace std;

class Bigraph {
    const int N, M;
    vector<vector<int> > adj;
    int idl(int i) { return i; }
    int idr(int j) { return N + j; }
public:
    Bigraph(int n, int m) : N(n), M(m), adj(n+m) {}
    void add_edge(int i, int j) {
        assert(0 <= i);
        assert(i < N);
        assert(0 <= j);
        assert(j < M);
        const int iid = idl(i), jid = idr(j);
        adj[iid].push_back(jid);
        adj[jid].push_back(iid);
    }
    vector<pair<int, int> > max_matching() {
        int match[N+M];
        bool visited[N+M];
        fill(match, match+N+M, -1);
        function<bool(int)> dfs = [&](int i) {
            visited[i] = true;
            for (int j : adj[i]) {
                if (visited[j]) continue;
                visited[j] = true;
                const int k = match[j];
                if (k == -1 || dfs(k)) {
                    match[j] = i;
                    match [i] = j;
                    return true;
                }
            }
            return false;
        };
        for (;;) {
            fill(visited, visited+N+M, false);
            bool found = false;
            for (int i = 0; i < N; i++) {
                if (visited[i] || match[i] >= 0) continue;
                if (dfs(i)) { found = true; break; }
            }
            if (!found) break;
        }
        vector<pair<int, int> > result;
        for (int i = 0; i < N; i++)
            if (match[i] >= 0) result.push_back({i, match[i]-N});
        return result;
    }
};

int main() {
    int n, m; cin >> n >> m;
    int a[n][m], b[n][m];
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) cin >> a[i][j];
    for (int k = 0; k < m; k++) {
        Bigraph bg(n, n);
        for (int i = 0; i < n; i++)
            for (int j = k; j < m; j++)
                bg.add_edge(i, (a[i][j] - 1) / m);
        vector<pair<int, int> > M = bg.max_matching();
        assert(M.size() == n);
        for (auto [i, q] : M) {
            int j = k;
            while ((a[i][j] - 1) / m != q) { j++; assert(j < m); }
            swap(a[i][k], a[i][j]);
        }
    }
    memcpy(b, a, sizeof a);
    int ct[m][n], c[n][m];
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) ct[j][i] = b[i][j];
    for (int i = 0; i < m; i++) sort(ct[i], ct[i]+n);
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) c[i][j] = ct[j][i];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) cout << b[i][j] << " ";
        cout << endl;
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) cout << c[i][j] << " ";
        cout << endl;
    }

    // check
    for (int i = 0; i < n; i++) {
        multiset<int> s1, s2;
        for (int j = 0; j < m; j++) {
            s1.insert(a[i][j]);
            s2.insert(b[i][j]);
        }
        assert(s1 == s2);
    }
    for (int j = 0; j < m; j++) {
        multiset<int> s1, s2;
        for (int i = 0; i < n; i++) {
            s1.insert(b[i][j]);
            s2.insert(c[i][j]);
        }
        assert(s1 == s2);
    }
}


Measured memory_bytes: 3472