#include <iostream>
#include <vector>
#include <tuple>
#include <limits>

template <class Cap, bool isDirect>
struct MaxFlow {
    struct Edge {
        int src, dst;
        Cap cap;
        Edge(int src, int dst, Cap cap)
            : src(src), dst(dst), cap(cap){};
    };

    using Edges = std::vector<Edge>;
    using Graph = std::vector<std::vector<int>>;

    Edges edges;
    Graph graph;
    std::vector<bool> visited;

    explicit MaxFlow(int n)
        : graph(n), visited(n) {}

    void span(int u, int v, Cap cap) {
        graph[u].push_back(edges.size());
        edges.emplace_back(u, v, cap);

        graph[v].push_back(edges.size());
        edges.emplace_back(v, u, (isDirect ? 0 : cap));
    }

    int dfs(int v, int g, Cap f) {
        if (v == g) return f;

        visited[v] = true;
        for (auto eidx : graph[v]) {
            auto& edge = edges[eidx];

            if (edge.cap > 0 && !visited[edge.dst]) {
                Cap df = dfs(edge.dst, g, std::min(f, edge.cap));

                if (df > 0) {
                    edge.cap -= df;
                    auto& redge = edges[eidx ^ 1];
                    redge.cap += df;
                    return df;
                }
            }
        }
        return 0;
    }

    Cap exec(int s, int g) {
        constexpr Cap INF = std::numeric_limits<Cap>::max();

        Cap ret = 0;
        while (true) {
            std::fill(visited.begin(), visited.end(), false);
            Cap flow = dfs(s, g, INF);
            if (flow == 0) return ret;
            ret += flow;
        }
    }
};

struct BiMatching {
    MaxFlow<int, true> mf;
    int n, m, s, g;

    explicit BiMatching(int n, int m)
        : mf(n + m + 2), n(n), m(m), s(n + m), g(n + m + 1) {
        for (int u = 0; u < n; ++u) {
            mf.span(s, enc(u, false), 1);
        }
        for (int v = 0; v < m; ++v) {
            mf.span(enc(v, true), g, 1);
        }
    }

    int enc(int v, bool side) {
        return v + (side ? n : 0);
    }

    void span(int u, int v) {
        mf.span(enc(u, false), enc(v, true), 1);
    }

    int exec() {
        return mf.exec(s, g);
    }

    std::vector<std::pair<int, int>> matching() {
        mf.exec(s, g);
        std::vector<std::pair<int, int>> ret;
        for (auto e : mf.edges) {
            if (e.src < e.dst &&
                e.src < n && e.dst < n + m &&
                e.cap == 0) {
                ret.emplace_back(e.src, e.dst - n);
            }
        }
        return ret;
    }
};

template <class T>
std::vector<T> vec(int len, T elem) { return std::vector<T>(len, elem); }

void solve() {
    int n, m;
    std::cin >> n >> m;

    auto nums = vec(n, vec(n, vec(0, 0)));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            int a;
            std::cin >> a;
            nums[i][(a - 1) / m].push_back(a);
        }
    }

    auto bs = vec(n, vec(m, 0));
    for (int j = 0; j < m; ++j) {
        BiMatching bm(n, n);
        for (int i = 0; i < n; ++i) {
            for (int c = 0; c < n; ++c) {
                if (nums[i][c].empty()) continue;
                bm.span(i, c);
            }
        }

        auto res = bm.matching();
        for (auto p : res) {
            int i, c;
            std::tie(i, c) = p;
            bs[i][j] = nums[i][c].back();
            nums[i][c].pop_back();
        }
    }

    for (auto& v : bs) {
        for (auto b : v) {
            std::cout << b << " ";
        }
        std::cout << std::endl;
    }

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            for (int k = 0; k < n; ++k) {
                if ((bs[k][j] - 1) / m == i) {
                    std::cout << bs[k][j] << " ";
                    break;
                }
            }
        }
        std::cout << std::endl;
    }
}

int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);

    solve();

    return 0;
}


Measured memory_bytes: 1540