#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define mod 1000000007
#define fi first
#define sc second
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())

int n,m,a[105][105];
int cnt[105][105];
vector<int>rem[105][105];
vector<int>id[105][105];

struct HopcroftKarp {
  vector< vector< int > > graph;
  vector< int > dist, match;
  vector< bool > used, vv;

  HopcroftKarp(int n, int m) : graph(n), match(m, -1), used(n) {}

  void add_edge(int u, int v) {
    graph[u].push_back(v);
  }

  void bfs() {
    dist.assign(graph.size(), -1);
    queue< int > que;
    for(int i = 0; i < graph.size(); i++) {
      if(!used[i]) {
        que.emplace(i);
        dist[i] = 0;
      }
    }

    while(!que.empty()) {
      int a = que.front();
      que.pop();
      for(auto &b : graph[a]) {
        int c = match[b];
        if(c >= 0 && dist[c] == -1) {
          dist[c] = dist[a] + 1;
          que.emplace(c);
        }
      }
    }
  }

  bool dfs(int a) {
    vv[a] = true;
    for(auto &b : graph[a]) {
      int c = match[b];
      if(c < 0 || (!vv[c] && dist[c] == dist[a] + 1 && dfs(c))) {
        match[b] = a;
        used[a] = true;
        return (true);
      }
    }
    return (false);
  }

  int bipartite_matching() {
    int ret = 0;
    while(true) {
      bfs();
      vv.assign(graph.size(), false);
      int flow = 0;
      for(int i = 0; i < graph.size(); i++) {
        if(!used[i] && dfs(i)) ++flow;
      }
      if(flow == 0) return (ret);
      ret += flow;
    }
  }

  void output(int id) {
    for(int i = 0; i < match.size(); i++) {
      if(~match[i]) {
        rem[match[i]][i].pb(id);
        cnt[match[i]][i]--;
      }
    }
  }
};

int num[10005];
int pt[105][105];
int ans[105][105];
int main(){
	cin >> n >> m;
	rep(i,n) rep(j,m){
		cin >> a[i][j];
		cnt[ (a[i][j]-1) / m ][i]++;
		id[ (a[i][j]-1) / m ][i].pb(a[i][j]);
	}
	
	rep(i,m){
		HopcroftKarp kaede(n,n);
		rep(a,n) rep(b,n) if(cnt[a][b]) kaede.add_edge(a,b);
		assert(kaede.bipartite_matching() == n);
		
		kaede.output(i);
	}
	
	rep(i,n) rep(j,n) assert(cnt[i][j] == 0);
	
	rep(i,n) rep(j,m){
		//cin >> a[i][j];
		//cnt[ (a[i][j]-1) / m ][i]++;
		num[a[i][j]] = rem[ (a[i][j]-1) / m ][i][pt[ (a[i][j]-1) / m ][i]++];
	}
	
	rep(i,n){
		rep(j,m){
			ans[i][num[a[i][j]]] = a[i][j];
		}
	}
	rep(i,n){
		rep(j,m) cout << ans[i][j] << " ";
		cout << endl;
	}
	
	rep(j,m){
		rep(i,n) rep(k,n){
			if(i < k && ans[i][j] > ans[k][j]) swap(ans[i][j],ans[k][j]);
		}
	}
	rep(i,n){
		rep(j,m) cout << ans[i][j] << " ";
		cout << endl;
	}
	
}

Measured memory_bytes: 1664