#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
using ll = long long;
using u64 = uint_fast64_t;
using pii =  pair<int, int>;
using pll =  pair<long long, long long>;
#define rep(i, n) for(int i = 0; i < (n); ++i)
#define all(x) (x).begin(),(x).end()
constexpr char ln =  '\n';
//constexpr long long MOD = 1000000007;
constexpr long long MOD = 998244353;
template<class T1, class T2> inline bool chmax(T1 &a, T2 b) { if (a < b) { a = b; return true;} return false; }
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) { if (a > b) { a = b; return true;} return false; }
inline int popcount(int x) {return __builtin_popcount(x);}
inline int popcount(long long x) {return __builtin_popcountll(x);}
void print() { cout << "\n"; }
template<class T, class... Args>
void print(const T &x, const Args &... args) {
    cout << x << " ";
    print(args...);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct BipartiteMatching {
    int N,time;
    vector<vector<int>> G;
    vector<int> match,used,dead;

    BipartiteMatching() {}
    BipartiteMatching(int N) : N(N), time(0), G(N),
                    match(N,-1), used(N,-1), dead(N,0) {}

    void add_edge(int u, int v) {
        G[u].emplace_back(v);
        G[v].emplace_back(u);
    }

    int dfs(int v) {
        used[v] = time;
        for(int u : G[v]) {
            if(dead[u]) continue;
            int w = match[u];
            if((w < 0) || (used[w] < time && dfs(w))) {
                match[v] = u;
                match[u] = v;
                return 1;
            }
        }
        return 0;
    }

    int build() {
        int res = 0;
        for (int v = 0; v < N; v++) {
            if (dead[v]) continue;
            if (match[v] < 0) {
                time++;
                res += dfs(v);
            }
        }
        return res;
    }

    int disable(int v) {
        assert(!dead[v]);
        int u = match[v];
        if(~u) match[u] = -1;
        match[v] = -1;
        dead[v] = 1;
        time++;
        return ~u ? dfs(u) - 1 : 0;
    }

    int enable(int v) {
        assert(dead[v]);
        dead[v] = 0;
        time++;
        return dfs(v);
    }
};

vector<int> G[100][100];
int main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);
    int N,M; cin >> N >> M;
    vector<vector<int>> A(N, vector<int>(M));
    rep(i,N) rep(j,M) {
        cin >> A[i][j];
        --A[i][j];
    }

    rep(i,N) {
        rep(j,M) {
            G[i][A[i][j]/M].emplace_back(A[i][j]);
        }
    }

    vector<vector<int>> B(N, vector<int>(M));
    rep(i,M) {
        BipartiteMatching BM(N*2);
        rep(j,N) {
            rep(k,N) {
                if ((int)G[j][k].size()) BM.add_edge(j,k+N);
            }
        }
        BM.build();
        rep(j,N) {
            int k = BM.match[j] - N;
            B[j][i] = G[j][k].back();
            G[j][k].pop_back();
        }
    }

    auto C = B;
    rep(i,M) {
        rep(j,N) {
            int val = 1e9, idx = 0;
            for (int k = j; k < N; k++) {
                if (chmin(val,C[k][i])) idx = k;
            }
            if (idx != j) swap(C[j][i],C[idx][i]);
        }
    }

    rep(i,N) {
        rep(j,M) {
            cout << B[i][j]+1 << " ";
        }
        cout << ln;
    }
    rep(i,N) {
        rep(j,M) {
            cout << C[i][j]+1 << " ";
        }
        cout << ln;
    }
}


Measured memory_bytes: 4360