#include <bits/stdc++.h>

#ifdef HOME
#define db(x) cerr << #x << " = " << x << endl
#define db3(x, y, z) cerr << "(" << #x << ", " << #y << ", " << #z << ") = (" << x << ", " << y << ", " << z << ")" << endl
#define db2(x, y) cerr << "(" << #x << ", " << #y << ") = (" << x << ", " << y << ")" << endl
#define dbv(a) cerr << #a << " = "; for (auto xxx: a) cerr << xxx  << " "; cerr << endl
#else
#define db(x) ;
#define db3(x, y, z) ;
#define db2(x, y) ;
#define dbv(a) ;
#endif

using namespace std;
typedef long long ll;
typedef double dbl;


const int INF = (int)1.01e9;

struct Edge {
    int to, cap, flow;
};

struct Graph {
    int n;
    vector<vector<int> > e;
    vector<Edge> edges;
    vector<int> d, c;

    Graph() {}
    Graph(int _n) {
        n = _n;
        e.resize(n);
    }

    void addEdge(int from, int to, int cap) {
        e[from].push_back(edges.size());
        edges.push_back(Edge({to, cap, 0}));
        e[to].push_back(edges.size());
        edges.push_back(Edge({from, 0, 0}));
    }

    bool bfs() {
        d.assign(n, INF);
        c.assign(n, 0);
        vector<int> q(n);
        int qL = 0, qR = 0;
        d[0] = 0;
        q[qR++] = 0;
        while (qL < qR) {
            int v = q[qL++];
            for (int i = 0; i < (int)e[v].size(); i++) {
                Edge cur = edges[e[v][i]];
                if (d[cur.to] > d[v] + 1 && cur.flow < cur.cap) {
                    d[cur.to] = d[v] + 1;
                    q[qR++] = cur.to;
                }
            }
        }
        return d[n - 1] != INF;
    }

    int dfs(int v, int flow) {
        if (v == n - 1) return flow;
        if (flow == 0) return 0;
        for (int &i = c[v]; i < (int)e[v].size(); i++) {
            Edge cur = edges[e[v][i]];
            if (d[cur.to] != d[v] + 1) continue;
            int pushed = dfs(cur.to, min(flow, cur.cap - cur.flow));
            if (pushed > 0) {
                edges[e[v][i]].flow += pushed;
                edges[e[v][i] ^ 1].flow -= pushed;
                return pushed;
            }
        }
        return 0;
    }

    ll flow() {
        ll flow = 0;
        while (bfs()) {
            while (int pushed = dfs(0, INF)) {
                flow += pushed;
            }
        }
        return flow;
    }
};

void solve(vector<vector<int>> a) {
    int n = a.size();
    int m =a[0].size();

    vector<vector<int>> b(n, vector<int>(m, -1));

    /*Graph gr(1 + n * m + n * m + 1);
    for (int x = 0; x < n; x++) {
        for (int y = 0; y < m; y++) {
            gr.addEdge(0, 1 + x * m + y, 1);
            for (int c = 0; c < m; c++) {
                gr.addEdge(1 + x * m + y, 1 + n * m + c * n + a[x][y] / m, 1);
            }
        }
    }
    for (int i = 0; i < n * m; i++) gr.addEdge(1 + n * m + i, 1 + n * m + n * m, 1);


    int f = gr.flow();
    assert(f == n * m);
    for (int x = 0; x < n; x++) {
        for (int y = 0; y < m; y++) {
            int from = 1 + x * m + y;
            int cnt = 0;
            for (int id : gr.e[from]) {
                auto ed = gr.edges[id];
                if (ed.flow > 0) {
                    int to = ed.to - 1 - n * m;
//                    db2(from-1, to);
                    assert(0 <= to && to < n * m);
                    int col = to / n;
                    db2(from-1, col);
                    b[x][col] = a[x][y];
                    cnt++;
                }
            }
            assert(cnt == 1);
        }
    }
    for (int i = 0; i < n; i++) {
        dbv(b[i]);
    }*/



    /*vector<vector<int>> was(m, vector<int>(n));
    for (int i = 0; i < n; i++) {
        Graph gr(1 + m + m + 1);
        for (int j = 0; j < m; j++) {
            gr.addEdge(0, 1 + j, 1);
            gr.addEdge(1 + m + j, 1 + m + m, 1);

            for (int k = 0; k < m; k++) {
                if (!was[k][a[i][j] / m]) {
                    gr.addEdge(1 + j, 1 + m + k, 1);
                }
            }
        }
        int f = gr.flow();
        db(f);
        assert(f == m);
        for (int j = 0; j < m; j++) {
            int from = 1 + j;
            for (int id : gr.e[from]) {
                if (gr.edges[id].flow <= 0) continue;
                int to = gr.edges[id].to - 1 - m;
//                    db2(j, to);
                assert(0 <= to && to < m);
                b[i][to] = a[i][j];
                was[to][a[i][j] / m] = 1;
            }
        }
        vector<int> t(m);
        for (int j = 0; j < m; j++) t[j] = b[i][j] / m;
            dbv(b[i]);
            dbv(t);
    }*/

    /*
    vector<vector<pair<int, int>>> vct(n);
    for (int i = 0; i < n; i++) {
        for (int j= 0; j < m; j++) {
            vct[a[i][j]/m].push_back({i, j});
        }
    }
    for (int col = 0; col < n; col++) {
        Graph gr(1 + m + m + 1);
        for (int j = 0; j < m; j++) {
            gr.addEdge(0, 1 + j, 1);
            gr.addEdge(1 + m + j, 1 + m + m, 1);

            for (int k = 0; k < m; k++) {
                if (b[vct[col][j].first][k] == -1) {
                    gr.addEdge(1 + j, 1 + m + k, 1);
                }
            }
        }
        int f = gr.flow();
        assert(f == m);
        for (int j = 0; j < m; j++) {
            int from = 1 + j;
            for (int id : gr.e[from]) {
                if (gr.edges[id].flow <= 0) continue;
                int to = gr.edges[id].to - 1 - m;
                assert(0 <= to && to < m);
                b[vct[col][j].first][to] = a[vct[col][j].first][vct[col][j].second];
            }
        }
    }*/

    b = a;
    for (int j = 0; j < m; j++) {
        Graph gr(1 + n + n + 1);
        vector<vector<int>> has(n, vector<int>(n));
        for (int x = 0; x < n; x++) for (int y = j; y < m; y++) has[x][b[x][y] / m] = 1;

        for (int i = 0; i < n; i++) {
            gr.addEdge(0, 1 + i, 1);
            gr.addEdge(1 + n + i, 1 + n + n, 1);
            for (int t = 0; t < n; t++) {
                if (has[i][t]) {
                    gr.addEdge(1 + i, 1 + n + t, 1);
                }
            }
        }
        int f = gr.flow();
        db(f);
        assert(f == n);
        for (int i = 0; i < n; i++) {
            int from = 1 + i;
            for (int id : gr.e[from]) {
                if (gr.edges[id].flow <= 0) continue;
                int to = gr.edges[id].to - 1 - n;
//                    db2(j, to);
                assert(0 <= to && to < n);
                for (int t = j; t < m; t++) if (b[i][t] / m == to) {
                    swap(b[i][t], b[i][j]);
                    break;
                }
            }
            db(b[i][j]);
        }
    }

    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) assert(b[i][j] != -1);

    vector<vector<int>> c(n, vector<int>(m, -1));
    for (int j = 0; j < m; j++) {
        vector<int> v(n);
        for (int i =0 ; i < n; i++) v[i] = b[i][j];
        sort(v.begin(), v.end());
        for (int i = 0; i < n; i++) c[i][j] = v[i];
    }

    for (int i= 0; i < n; i++) {
        for (int j= 0; j <m; j++) {
            printf("%d%c", b[i][j]+1, " \n"[j + 1 == m]);
        }
    }
    for (int i= 0; i < n; i++) {
        for (int j= 0; j <m; j++) {
            printf("%d%c", c[i][j]+1, " \n"[j + 1 == m]);
        }
    }
}

int main() {
#ifdef HOME
    assert(freopen("in", "r", stdin));
#endif

    for (int it = 499; 0; it++ ){
        mt19937 rnd(it);
        db(it);

        const int N = 4;
        int n =rnd() % N + 1;
        int m = rnd() % N + 1;
        vector<int> p(n * m);
        iota(p.begin(), p.end(), 0);
        shuffle(p.begin(), p.end(), rnd);
        vector<vector<int>> a(n, vector<int>(m));
        for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) a[i][j] = p[i * m + j];

        for (int i = 0; i < n; i++) {
            dbv(a[i]);
        }
        solve(a);
    }

    int n, m;
    while (scanf("%d%d", &n, &m) == 2) {
        vector<vector<int>> a(n, vector<int>(m));
        for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) scanf("%d", &a[i][j]), a[i][j]--;

        solve(a);
    }

#ifdef HOME
    cerr << "time: " << clock() * 1.0 / CLOCKS_PER_SEC << endl;
#endif
}


Measured memory_bytes: 1092