#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>

using namespace std;

class BipartiteMatching {
    public:
    BipartiteMatching(int n, int m);
    ~BipartiteMatching();
    void add_edge(int left, int right);
    int bipartite_matching();
    int get_matching(int left);
    
    private:
    int n;
    int m;
    int *level;
    int *que;
    bool *used;
    int *match;
    vector <vector <int> > graph;
    void bfs();
    bool dfs(int from);
};

BipartiteMatching::BipartiteMatching(int n, int m) : n(n), m(m), graph(n + m) {
    level = (int *)malloc(sizeof(int) * n);
    que = (int *)malloc(sizeof(int) * n);
    used = (bool *)malloc(sizeof(bool) * n);
    match = (int *)malloc(sizeof(int) * (n + m));
}

BipartiteMatching::~BipartiteMatching() {
    free(level);
    free(que);
    free(used);
    free(match);
}

void BipartiteMatching::add_edge(int left, int right) {
    graph[left].push_back(n + right);
}

int BipartiteMatching::bipartite_matching() {
    int matching = 0;
    for (int i = 0; i < n + m; i++) match[i] = -1;
    while (1) {
        int current = 0;
        bfs();
        for (int i = 0; i < n; i++) used[i] = false;
        for (int i = 0; i < n; i++) {
            if (match[i] < 0 && dfs(i)) current++;
        }
        if (current == 0) return matching;
        matching += current;
    }
}

int BipartiteMatching::get_matching(int left) {
    return match[left] - n;
}

void BipartiteMatching::bfs() {
    int qs = 0, qt = 0;
    for (int i = 0; i < n; i++) level[i] = -1;
    for (int i = 0; i < n; i++) {
        if (match[i] < 0) {
            level[i] = 0;
            que[qt++] = i;
        }
    }
    
    while (qs < qt) {
        int now = que[qs++];
        for (int i = 0; i < graph[now].size(); i++) {
            int to = graph[now][i], next = match[to];
            if (next >= 0 && level[next] < 0) {
                level[next] = level[now] + 1;
                que[qt++] = next;
            }
        }
    }
}

bool BipartiteMatching::dfs(int from) {
    used[from] = true;
    for (int i = 0; i < graph[from].size(); i++) {
        int to = graph[from][i], next = match[to];
        if (next < 0 || (!used[next] && level[from] < level[next] && dfs(next))) {
            match[from] = to;
            match[to] = from;
            return true;
        }
    }
    return false;
}

int a[100][100];
int aa[100][100];
int b[100][100];

int main() {
    int n, m, i, j, k, l;
    
    scanf("%d %d", &n, &m);
    
    for (i = 0; i < n; i++) {
        for (j = 0; j < m; j++) {
            scanf("%d", &a[i][j]);
            aa[i][j] = (a[i][j] - 1) / m;
        }
    }
    
    for (i = 0; i < m; i++) {
        BipartiteMatching bm(n, n);
        
        for (j = 0; j < n; j++) {
            for (k = 0; k < m; k++) {
                if (a[j][k] == -1) continue;
                
                bm.add_edge(j, aa[j][k]);
            }
        }
        
        bm.bipartite_matching();
        
        for (j = 0; j < n; j++) {
            int x = bm.get_matching(j);
            
            for (k = 0; k < m; k++) {
                if (a[j][k] == -1) continue;
                
                if (aa[j][k] == x) {
                    b[j][i] = a[j][k];
                    a[j][k] = -1;
                    
                    break;
                }
            }
        }
    }
    
    for (i = 0; i < n; i++) {
        for (j = 0; j < m; j++) {
            if (j > 0) putchar(' ');
            printf("%d", b[i][j]);
        }
        puts("");
    }
    
    for (i = 0; i < m; i++) {
        vector <int> v;
        
        for (j = 0; j < n; j++) v.push_back(b[j][i]);
        sort(v.begin(), v.end());
        
        for (j = 0; j < n; j++) b[j][i] = v[j];
    }
    
    for (i = 0; i < n; i++) {
        for (j = 0; j < m; j++) {
            if (j > 0) putchar(' ');
            printf("%d", b[i][j]);
        }
        puts("");
    }
    
    return 0;
}


Measured memory_bytes: 512