#include <iostream>
#include <vector>
#include <queue>
using namespace std;

const int INF = 100000000;

template <typename T>
struct Edge
{
    int to;
    T cap;
    int rev;
    int id;
};

template <typename T>
struct Flow
{
    int n;
    vector<int> d;
    vector<int> nx;
    vector<vector<Edge<T>>> g;
    
    Flow(){}
    
    Flow(int n) : n(n){
        d.resize(n);
        nx.resize(n);
        g.resize(n);
    }
    
    void add_edge(int from, int to, T cap, int id = -1){
        g[from].push_back((Edge<T>){to, cap, (int)g[to].size(), id});
        g[to].push_back((Edge<T>){from, 0, (int)g[from].size() - 1, -1});
    }
    
    void bfs(int r){
        fill(d.begin(), d.end(), n);
        queue<int> que;
        d[r] = 0;
        que.push(r);
        while(que.size()){
            int u = que.front();
            que.pop();
            for(Edge<T> e : g[u]){
                int v = e.to;
                if(e.cap > 0 && d[v] == n){
                    d[v] = d[u] + 1;
                    que.push(v);
                }
            }
        }
    }
    
    T dfs(int u, int s, T f){
        if(u == s) return f;
        for(int &i = nx[u]; i < (int)g[u].size(); i++){
            Edge<T> &e = g[u][i];
            int v = e.to;
            if(d[v] <= d[u] || e.cap == 0) continue;
            T fl = dfs(v, s, min(f, e.cap));
            if(fl > 0){
                e.cap -= fl;
                g[e.to][e.rev].cap += fl;
                return fl;
            }
        }
        return 0;
    }
    
    T max_flow(int r, int s){
        T res = 0;
        while(true){
            bfs(r);
            if(d[s] == n) return res;
            for(int i = 0; i < n; i++) nx[i] = 0;
            for(T f; (f = dfs(r, s, INF)) > 0;) res += f;
        }
    }
};

struct Bipartite_Matching
{
    int n;
    int m;
    Flow<int> g;
    vector<int> match;
    
    Bipartite_Matching(int n, int m) : n(n), m(m){
        g.n = n + m + 2;
        g.d.resize(g.n);
        g.nx.resize(g.n);
        g.g.resize(g.n);
        for(int i = 0; i < n; i++) g.add_edge(n + m, i, 1);
        for(int i = n; i < n + m; i++) g.add_edge(i, n + m + 1, 1);
    }
    
    void add_edge(int i, int j, int id = -1){
        g.add_edge(i, j + n, 1, id);
    }
    
    int max_matching(){
        g.max_flow(n + m, n + m + 1);
        for(int i = 0; i < n; i++){
            for(int j = 1; j < (int)g.g[i].size(); j++){
                if(g.g[i][j].cap == 0) match.push_back(g.g[i][j].id);
            }
        }
        return (int)match.size();
    }
};

int main()
{
    int n, m;
    cin >> n >> m;
    int a[102][102];
    int d[10005];
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            cin >> a[i][j];
            a[i][j]--;
            d[a[i][j]] = i;
        }
    }
    int b[10005];
    for(int i = 0; i < n * m; i++) b[i] = -1;
    for(int k = 0; k < m; k++){
        Bipartite_Matching g(n, n);
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(b[a[i][j]] == -1) g.add_edge(i, a[i][j] / m, a[i][j]);
            }
        }
        g.max_matching();
        for(int id : g.match) b[id] = k;
    }
    int c[105][105];
    for(int i = 0; i < n * m; i++){
        c[d[i]][b[i]] = i;
    }
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++) cout << c[i][j] + 1 << " ";
        cout << endl;
    }
    for(int i = 0; i < n * m; i++){
        c[i / m][b[i]] = i;
    }
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++) cout << c[i][j] + 1 << " ";
        cout << endl;
    }
}


Measured memory_bytes: 4180