#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
typedef pair<ll, ll> LP;
typedef vector<ll> vec;
typedef vector<string> svec;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-5;

#include<cstring>
const int max_v = 100000;
struct edge { int to, cap, rev,isrev,id; };
vector<edge> G[max_v];
bool used[max_v];
void add_edge(int from, int to, int cap) {
	G[from].push_back(edge{ to, cap, (int)G[to].size(),0,-1 });
	G[to].push_back(edge{ from, 0, (int)G[from].size() - 1,1,-1 });
}
vector<vector<P>> keiro;
bool valid[5000];
vector<P> cur;
int dfs(int v, int t, int f) {
	if (v == t)return f;
	used[v] = true;
	for (int i = 0; i < (int)G[v].size(); i++) {
		edge &e = G[v][i];
		if (!used[e.to] && e.cap > 0) {

			int d = dfs(e.to, t, min(f, e.cap));
			if (d > 0) {
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				if (e.isrev) {
					int pastid = e.id;
					vector<P> memo = keiro[pastid];
					vector<P> ad;
					per(j, (int)memo.size()) {
						if (memo[j].first == v) {
							for (int k = j; k < memo.size(); k++) {
								ad.push_back(memo[k]);
							}
							keiro[pastid].resize(j - 1);
							per(k, (int)cur.size()) {
								keiro[pastid].push_back(cur[k]);
								edge &ee = G[cur[k].first][cur[k].second];
								ee.id = pastid;
								G[ee.to][ee.rev].id = pastid;
							}

							break;
						}
					}
					cur = ad;
					rep(j, cur.size()) {
						edge &ee = G[cur[j].first][cur[j].second];
						ee.id = keiro.size();
						G[ee.to][ee.rev].id = keiro.size();
					}
				}
				else {
					cur.push_back({ v,i });
					e.id = keiro.size();
					G[e.to][e.rev].id = keiro.size();
				}
				return d;
			}
		}
	}
	return 0;
}
int max_flow(int s, int t) {
	int flow = 0;
	for (;;) {
		memset(used, 0, sizeof(used));
		cur.clear();
		int f = dfs(s, t, mod);
		reverse(cur.begin(), cur.end());
		keiro.push_back(cur);
		if (f == 0)return flow;
		flow += f;
	}
}

int a[100][100];
vector<int> c[100][100];
int ans1[100][100];

void solve() {
	int n, m; cin >> n >> m;
	rep(i, n) {
		rep(j, m) {
			cin >> a[i][j]; a[i][j]--;
			c[i][a[i][j]/m].push_back(a[i][j]);
		}
	}
	int s = 2 * n; int t = s + 1;
	rep(k, m) {
		rep(i, 2 * n + 2)G[i].clear();
		keiro.clear();
		rep(i, n) {
			add_edge(s, i, 1);
			add_edge(i+n, t, 1);
			rep(j, n) {
				if (c[i][j].size()) {
					add_edge(i, j+n, 1);
				}
			}
		}
		int f = max_flow(s, t);
		//cout << "?? " << k << " " << f << endl;
		assert(f == n);
		rep(i, f) {
			int m1, m2;
			rep(j, keiro[i].size()) {
				int x = keiro[i][j].first;
				//cout << i << " " << x << endl;
				if (x < n) {
					m1 = x;
				}
				else if (x < 2 * n) {
					m2 = x-n;
				}
			}
			ans1[m1][k] = c[m1][m2].back(); c[m1][m2].pop_back();
		}
	}
	rep(i, n) {
		rep(j, m) {
			if (j > 0)cout << " ";
			cout << ans1[i][j]+1;
		}
		cout << endl;
	}
	int ans2[100][100];
	rep(j, m) {
		vector<P> v;
		rep(i, n) {
			v.push_back({ ans1[i][j] / m,ans1[i][j] });
		}
		sort(v.begin(), v.end());
		rep(i, n) {
			ans2[i][j] = v[i].second;
		}
	}
	rep(i, n) {
		rep(j, m) {
			if (j > 0) {
				cout << " ";

			}
			cout << ans2[i][j] + 1;
		}
		cout << endl;
	}
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(5);
	//init();
	solve();
	//cout << "finish" << endl;
	//stop
	return 0;
}

Measured memory_bytes: 3968