#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<pii> vp;
const int inf = 1e9;
const ll INF = 1e18;
const db eps = 1e-10;

#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define ep emplace
#define mem(a) memset(a, 0, sizeof(a))
#define copy(a, b) memcpy(a, b, sizeof(b))
#define PA cout << "pass\n"
#define lowbit(x) (x & -x)
#define all(x) x.begin(), x.end()
#define TM cout << db(clock()) / CLOCKS_PER_SEC << '\n'

mt19937 mrand(chrono::high_resolution_clock::now().time_since_epoch().count());

template<class T>inline void upmin(T &x, T y) {x = x > y ? y : x;}
template<class T>inline void upmax(T &x, T y) {x = x < y ? y : x;}

#include<bits/stdc++.h>
using namespace std;

int n, m;
const int maxn = 220;

struct edge {
    int from, to, cap, flow;
};

template<class T>
struct Dinic {
    int s, t, tot;
    vector<edge> edges;
    vector<int> G[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxn];
    T infinity;

    void init(T infinity) {
        edges.clear();
        for (int i = 0; i <= t; i++)G[i].clear();
        this->infinity = infinity;
    }

    void addedge(int from, int to, int cap) {
        edges.push_back(edge{from, to, cap, 0});
        edges.push_back(edge{to, from, 0, 0});
        tot = edges.size();
        G[from].push_back(tot - 2);
        G[to].push_back(tot - 1);
    }

    bool bfs() {
        memset(vis, 0, sizeof(vis));
        queue<int> q;
        q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while (!q.empty()) {
            int x = q.front();
            q.pop();
            for (int i = 0; i < G[x].size(); i++) {
                edge &e = edges[G[x][i]];
                if (!vis[e.to] && e.cap > e.flow) {
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }

    T dfs(int x, T a) {
        if (x == t || a == 0)return a;
        T flow = 0, f;
        for (int &i = cur[x]; i < G[x].size(); i++) {
            edge &e = edges[G[x][i]];
            if (d[x] + 1 == d[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0) {
                e.flow += f;
                edges[G[x][i] ^ 1].flow -= f;
                flow += f;
                a -= f;
                if (a == 0)break;
            }
        }
        return flow;
    }

    T maxflow() {
        T flow = 0;
        while (bfs()) {
            memset(cur, 0, sizeof(cur));
            flow += dfs(s, infinity);
        }
        return flow;
    }

    /*求最小点覆盖，从s出发，左边标记过的点和右边没标记过的点构成最小点覆盖，除去这些点外的点构成最大独立集。

    void dfs1(int u) {
        ok[u] = 1;
        for (int i = 0; i < G[u].size(); i++) {
            edge &e = edges[G[u][i]];
            if (e.cap > e.flow && !ok[e.to]) dfs1(e.to);
        }
    }*/
};

Dinic<int> sol;
vi pos[maxn][maxn];
int b[maxn][maxn], c[maxn][maxn];

int main(){
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            int x;
            scanf("%d", &x);
            pos[i][(x - 1) / m + 1].eb(x);
        }
    }
    for(int i = 1; i <= m; i++){
        sol.init(inf);
        sol.s = 0, sol.t = 2 * n + 1;
        for(int j = 1; j <= n; j++){
            for(int k = 1; k <= n; k++){
                if(pos[j][k].size()) sol.addedge(j, k + n, 1);
            }
            sol.addedge(0, j, 1);
            sol.addedge(j + n, sol.t, 1);
        }
        sol.maxflow();
        for(int j = 0; j < sol.edges.size(); j += 2){
            auto &e = sol.edges[j];
            if(e.from >= 1 && e.from <= n && e.to > n && e.to <= 2 * n && e.flow > 0){
                int now = pos[e.from][e.to - n].back();

                pos[e.from][e.to - n].pop_back();
                b[e.from][i] = now;
                c[e.to - n][i] = now;
            }
        }
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            printf("%d%c", b[i][j], " \n"[j == m]);
        }
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            printf("%d%c", c[i][j], " \n"[j == m]);
        }
    }
    return 0;
}


Measured memory_bytes: 2480