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

typedef long long ll;
typedef double lf;
typedef long double Lf;
typedef pair <int,int> pii;
typedef pair <ll, ll> pll;

#define TRACE(x) cerr << #x << "  " << x << endl
#define FOR(i, a, b) for (int i = (a); i < int(b); i++)
#define REP(i, n) FOR(i, 0, n)
#define all(x) (x).begin(), (x).end()
#define _ << " " <<

#define fi first
#define sec second
#define mp make_pair
#define pb push_back

typedef vector <vector <int> > mat;

const int MAXN = 510;

struct Matching {
  vector <int> v[MAXN * 10];
  vector <int> par, bio;
  int n, m;

  void init(int _n, int _m) {
    n = _n;
    m = _m;
    bio.clear();
    par.clear();
    REP(i, 2 * max(n, m)) {
      v[i].clear();
    }
  }

  int upari(int cvor) {
    bio[cvor] = 1;

    REP(i, (int)v[cvor].size()) {
      int ncvor = v[cvor][i];
      if (par[ncvor] == -1) {par[ncvor] = cvor; return 1;}
      if (bio[par[ncvor]]) continue;
      if (upari(par[ncvor])) {par[ncvor] = cvor; return 1;}
    }
    return 0;
  }

  void edge(int a, int b) {
    v[a].pb(b + n);
    v[b + n].pb(a);
  }

  vector <int> run() {
    int sol = 0;
    par.clear();
    par.resize(2 * max(n, m), -1);
    REP(i, n) {
      bio.clear();
      bio.resize(2 * max(n, m), 0);
      sol += upari(i);
    }
    REP(i, 2 * max(n, m)) v[i].clear();
    return par;
  }
}M;

int n, m;

mat p, kraj, uzet;
vector <mat> ans, ans1;

void myassert(bool ok) {
  if (!ok) exit(0);
  return;
}

void print(mat &pr) {
  set <int> prov;
  REP(i, n) {
    REP(j, m) {
      printf("%d ",pr[i][j] + 1);
      if (prov.count(pr[i][j])) TRACE(i _ j _ pr[i][j]);
      assert(prov.count(pr[i][j]) == 0);
      myassert(pr[i][j] >= 0 && pr[i][j] <= n * m-1);
      prov.insert(pr[i][j]);
    }
    puts("");
  }
}

int cnt_col[MAXN][MAXN];

void init() {
  kraj.clear();
  p.clear();
  ans.clear();
  ans1.clear();
  uzet.clear();
  kraj.resize(n, vector <int>(m, 0));
  p.resize(n, vector<int>(m, 0));
  uzet.resize(n, vector<int>(m, 0));
  REP(i, n + 1) REP(j, m + 1) cnt_col[i][j] = 0;
}

bool check2() {
  return false;
  bool ok = 1;
  mat p1 = p;
  vector <int> per(m, 0);
  REP(i, m) per[i] = i;
  REP(i, n) {
    vector <int> t;
    REP(j, m) t.pb(p[i][j] % m);
    sort(all(t));
    if (t != per) ok = 0;
  }
  if (!ok) return false;
  
  REP(i, n) {
    vector <pii> t;
    REP(j, m) t.pb({p[i][j] % m, p[i][j]});
    sort(all(t));
    REP(j, m) p[i][j] = t[j].sec;
  }

  if (p1 != p) ans1.pb(p);
  if (p != kraj) ans1.pb(kraj);

  if (ans.empty() || ans1.size() < ans.size()) ans = ans1;

  return true;
}

void solve() {
  scanf("%d %d",&n,&m);
  init();
  REP(i, n) {
    REP(j, m) {
      kraj[i][j] = i * m + j;
      scanf("%d",&p[i][j]);
      p[i][j]--;
      cnt_col[j][p[i][j] / m]++;
    }
  }

  
  if (p == kraj) {
  //  puts("0");
    ans.pb(p);
    ans.pb(p);
    for (auto t : ans) print(t);
    return;
  }

  bool ok = 1;
  REP(i, n) {
    REP(j, m) {
      if (cnt_col[i][j] != 1) ok = 0;
    }
  }

  mat last = p;
  if (ok) {
    mat p1 = p;
    REP(j, m) {
      vector <int> tu;
      REP(i, n) tu.pb(p[i][j]);
      sort(all(tu));
      REP(i, n) p[i][j] = tu[i];
    }
    if (p != p1) ans.pb(p);
    if (p != kraj) ans.pb(kraj);
  }
  p = last;

  if (check2() || ok) {
    //printf("%d\n",(int)ans.size());
  if (ans.size() > 2) ans.pop_back();
  if (ans.size() == 1) ans.pb(kraj);
    for (auto &t : ans) print(t);
    return;
  }

  p = last;

  mat pom;
  pom.resize(n, vector<int>(m, 0));


  REP(col, m) {
    M.init(n, n);
    REP(i, n) {
      vector <int> color(n, -1);
      REP(j, m) {
        if (uzet[i][j] || color[p[i][j] / m] != -1) continue;
        color[p[i][j] / m] = p[i][j];
        M.edge(i, p[i][j] / m);
      }
    }
    auto par = M.run();
    REP(i, n) {
      vector <int> color(n, -1);
      REP(j, m) {
        if (uzet[i][j] || color[p[i][j] / m] != -1)  continue;
        if (par[p[i][j]/m+n] != i) continue;
        color[p[i][j] / m] = p[i][j];
        pom[i][col] = p[i][j];
        uzet[i][j] = 1;
      }
    }
  }

  ans.pb(pom);
  mat p1 = pom;
  REP(j, m) {
    vector <int> tu;
    REP(i, n) tu.pb(pom[i][j]);
    sort(all(tu));
    REP(i, n) pom[i][j] = tu[i];
  }
  if (p1 != pom) ans.pb(pom);
  if (pom != kraj) ans.pb(kraj);
  //printf("%d\n",(int)ans.size());
  if (ans.size() > 2) ans.pop_back();
  if (ans.size() == 1) ans.pb(kraj);
  for (auto &t : ans) print(t);
}

int main() {
  int t;
  //scanf("%d",&t);
  t = 1;
  while (t--) solve();
  return 0;
}



Measured memory_bytes: 1536