#include <bits/stdc++.h>
using namespace std;
using Int = long long;
int PREP = (cin.tie(nullptr), ios::sync_with_stdio(false), cout << fixed << setprecision(9), 0);
//int SEGV = getenv("D") || (exit(system("D= SEGFAULT_SIGNALS=all catchsegv ./prog.exe") >> 8), 0);
struct MaxFlow {
    vector<vector<int>> G, cap, flow;
    MaxFlow(int n) {
        G.resize(n);
        cap.resize(n, vector<int>(n));
        flow.resize(n, vector<int>(n));
    }
    void add_edge(int s, int t, int c) {
        G[s].push_back(t);
        G[t].push_back(s);
        cap[s][t] += c;
    }
    int solve(int s, int t) {
        auto residual = [&](int a, int b) {
            return cap[a][b] - flow[a][b] + flow[b][a];
        };
        vector<int> visited(G.size());
        auto dfs = [&](auto &dfs, int a, int b, int f) -> int {
            if (visited[a]) return 0;
            if (a == b) return f;
            visited[a] = 1;
            for (int n : G[a]) {
                int r = residual(a, n);
                if (r > 0) {
                    int ans = dfs(dfs, n, b, min(f, r));
                    if (ans > 0) {
                        flow[a][n] += ans;
                        return ans;
                    }
                }
            }
            return 0;
        };
        int ans = 0;
        for (;;) {
            fill(begin(visited), end(visited), 0);
            int f = dfs(dfs, s, t, 1e9);
            if (f == 0) break;
            ans += f;
        }
        return ans;
    }
    int get_flow(int s, int t) {
        return flow[s][t] - flow[t][s];
    }
};
int main() {
    int N, M; cin >> N >> M;
    vector<vector<int>> A(N, vector<int>(M)), B(N, vector<int>(M));
    for (auto &row : A) for (auto &a : row) cin >> a, a--;
    for (int col = 0; col < M; col++) {
        MaxFlow mf(N + N + 2);
        for (int row = 0; row < N; row++) {
            for (int val = 0; val < N; val++) {
                for (int j = 0; j < M; j++) {
                    if (A[row][j] != -1 && A[row][j] / M == val) {
                        mf.add_edge(val, N + row, 1);
                        break;
                    }
                }
            }
        }
        int S = N + N, T = N + N + 1;
        for (int val = 0; val < N; val++) {
            mf.add_edge(S, val, 1);
        }
        for (int row = 0; row < N; row++) {
            mf.add_edge(N + row, T, 1);
        }
        mf.solve(S, T);
        for (int row = 0; row < N; row++) {
            int val = 0;
            while (mf.get_flow(val, N + row) == 0) val++;
            for (int j = 0; j < M; j++) {
                if (A[row][j] != -1 && A[row][j] / M == val) {
                    B[row][col] = A[row][j];
                    A[row][j] = -1;
                    break;
                }
            }
        }
    }
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cout << B[i][j] + 1 << " \n"[j == M - 1];
        }
    }
    for (int col = 0; col < M; col++) {
        vector<int> vec(N);
        for (int i = 0; i < N; i++) {
            vec[i] = B[i][col];
        }
        sort(begin(vec), end(vec));
        for (int i = 0; i < N; i++) {
            B[i][col] = vec[i];
        }
    }
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cout << B[i][j] + 1<< " \n"[j == M - 1];
        }
    }
    return 0;
}


Measured memory_bytes: 868