#include "bits/stdc++.h"
using namespace std;
typedef long long ll;

class FlowNetwork {
 protected:
  vector<vector<int>> grafo;
  vector<vector<ll>> cap;

 private:
  vector<int> label;
  vector<ll> excess;
  vector<bool> reach;

  void norm() {
    for (auto& v : grafo) {
      sort(v.begin(), v.end());
      v.erase(unique(v.begin(), v.end()), v.end());
    }
  }
  void push(int v, int u) {
    ll delta = min(excess[v], cap[v][u]);
    excess[v] -= delta;
    excess[u] += delta;
    cap[v][u] -= delta;
    cap[u][v] += delta;
  }
  void relabel(int v) {
    label[v] = 1e9;
    for (int i : grafo[v]) {
      if (cap[v][i]) {
        label[v] = min(label[v], label[i] + 1);
      }
    }
  }

 public:
  FlowNetwork(int N)
      : grafo(N), cap(N, vector<ll>(N)), label(N), excess(N), reach(N) {}

  void addEdge(int v, int u, ll c) {
    grafo[v].push_back(u);
    grafo[u].push_back(v);
    cap[v][u] += c;
  }

  ll maxFlow(int S, int T) {
    norm();
    for (int i : grafo[S]) {
      excess[S] += cap[S][i];
    }
    label[S] = grafo.size() - 1;
    priority_queue<pair<int, int>> Q;
    Q.emplace(label[S], S);
    while (!Q.empty()) {
      int v = Q.top().second;
      Q.pop();
      while (excess[v]) {
        for (int i : grafo[v]) {
          if (cap[v][i] && (v == S || label[v] == label[i] + 1)) {
            push(v, i);
            if (i != S && i != T) {
              Q.emplace(label[i], i);
            }
          }
        }
        if (excess[v]) {
          relabel(v);
        }
      }
    }
    return excess[T];
  }

  vector<pair<int, int>> minCut(int S) {
    queue<int> Q;
    Q.push(S);
    reach[S] = true;
    while (!Q.empty()) {
      int v = Q.front();
      Q.pop();
      for (int i : grafo[v]) {
        if (!reach[i] && cap[v][i]) {
          Q.push(i);
          reach[i] = true;
        }
      }
    }
    vector<pair<int, int>> R;
    for (int i = 0; i < (int)reach.size(); i++) {
      for (int j : grafo[i]) {
        if (!reach[j] && cap[i][j] == 0) {
          R.emplace_back(i, j);
        }
      }
    }
    return R;
  }
};

class BipartiteMatching : private FlowNetwork {
 private:
  int N, M;

 public:
  BipartiteMatching(int n, int m) : FlowNetwork(n + m + 2), N(n), M(m) {
    for (int i = 0; i < N; i++) {
      FlowNetwork::addEdge(N + M, i, 1);
    }
    for (int i = 0; i < M; i++) {
      FlowNetwork::addEdge(N + i, N + M + 1, 1);
    }
  }

  void addEdge(int v, int u) {
    if (cap[v][N + u] == 0) {
      FlowNetwork::addEdge(v, N + u, 1);
    }
  }

  vector<pair<int, int>> maxMatch() {
    vector<pair<int, int>> match;
    match.reserve(maxFlow(N + M, N + M + 1));
    for (int i = 0; i < N + M + 2; i++) {
    }
    for (int i = 0; i < N; i++) {
      for (int j : grafo[i]) {
        if (N <= j && j < N + M && cap[j][i] > 0) {
          match.emplace_back(i, j - N);
        }
      }
    }
    return match;
  }
};

constexpr int MAXN = 107;

int grid[MAXN][MAXN];

int main() {
  int N, M;
  cin >> N >> M;
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
      cin >> grid[i][j];
    }
  }
  for (int k = 0; k < M; k++) {
    BipartiteMatching net(N, N);
    for (int i = 0; i < N; i++) {
      for (int j = k; j < M; j++) {
        net.addEdge(i, (grid[i][j] - 1) / M);
      }
    }
    auto match = net.maxMatch();
    for (auto p : match) {
      iter_swap(&grid[p.first][k],
                find_if(&grid[p.first][k], &grid[p.first][M],
                        [&](int v) { return (v - 1) / M == p.second; }));
    }
  }
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
      cout << grid[i][j] << ' ';
    }
    cout << '\n';
  }
  for (int j = 0; j < M; j++) {
    vector<int> C(N);
    for (int i = 0; i < N; i++) {
      C[i] = grid[i][j];
    }
    sort(C.begin(), C.end());
    for (int i = 0; i < N; i++) {
      grid[i][j] = C[i];
    }
  }
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
      cout << grid[i][j] << ' ';
    }
    cout << '\n';
  }

  return 0;
}


Measured memory_bytes: 792