#include <bits/stdc++.h>

using namespace std;

int read() {
  int res = 0; char c = getchar();
  while(!isdigit(c)) c = getchar();
  while(isdigit(c)) res = res * 10 + c - '0', c = getchar();
  return res;
}

namespace Dinic {
  struct Edge {
    int to, flow, id;
    Edge(): to(0), flow(0), id(0) {}
    Edge(int _t, int _f, int _i): to(_t), flow(_f), id(_i) {}
  };
  vector<Edge> edges;
  vector<int> G[818];
  int S, T, dep[818], cur[818];
  queue<int> que;
  void add(int u, int v, int flow, int num) {
    G[u].push_back(edges.size());
    edges.push_back(Edge(v, flow, num));
    G[v].push_back(edges.size());
    edges.push_back(Edge(u, 0, num));
  }
  bool bfs() {
    memset(dep, 0, sizeof(dep));
    while(!que.empty()) que.pop();
    dep[S] = 1, que.push(S);
    while(!que.empty()) {
      int now = que.front(); que.pop();
      int sz = G[now].size();
      for(int i = 0; i < sz; i++) {
        Edge e = edges[G[now][i]];
        if(!dep[e.to] && e.flow) {
          dep[e.to] = dep[now] + 1;
          que.push(e.to);
        }
      }
    }
    return dep[T] > 0;
  }
  int dfs(int x, int limit) {
    if(!limit || x == T) return limit;
    int res = 0, sz = G[x].size();
    for(int &i = cur[x]; i < sz && limit; i++) {
      Edge &e = edges[G[x][i]];
      if(dep[e.to] != dep[x] + 1) continue;
      int new_flow = dfs(e.to, min(e.flow, limit));
      if(!new_flow) continue;
      Edge &ie = edges[G[x][i] ^ 1];
      e.flow -= new_flow, ie.flow += new_flow;
      limit -= new_flow, res += new_flow;
    }
    return res;
  }
  int dinic() {
    int Max_flow = 0;
    while(bfs()) {
      memset(cur, 0, sizeof(cur));
      Max_flow += dfs(S, 0x3f3f3f3f);
    }
    return Max_flow;
  }
} using namespace Dinic;

int N, M, tmp[102], tmp_cnt;
int A[102][102];
int B[102][102];
int C[102][102];

int main() {
  N = read(), M = read();
  S = N << 1 | 1, T = S + 1;
  for(int i = 1; i <= N; i++)
    for(int j = 1; j <= M; j++)
      A[i][j] = read();
  for(int k = 1; k <= M; k++) {
    edges.clear();
    for(int i = 1; i <= T; i++)
      vector<int>().swap(G[i]);
    for(int i = 1; i <= N; i++) add(S, i, 1, 0);
    for(int i = 1; i <= N; i++) add(N + i, T, 1, 0);
    for(int i = 1; i <= N; i++) {
      for(int j = 1; j <= M; j++) {
        if(!A[i][j]) continue;
        int color = (A[i][j] - 1) / M + 1;
        add(i, N + color, 1, A[i][j]);
      }
    }
    int Max_flow = dinic();
    if(Max_flow != N) return puts("No"), 0;
    for(int i = 1; i <= N; i++) {
      int sz = G[i].size();
      for(int j = 0; j < sz; j++) {
        if(!edges[G[i][j]].flow) {
          B[i][k] = edges[G[i][j]].id;
          break;
        }
      }
    }
    for(int i = 1; i <= N; i++) {
      for(int j = 1; j <= M; j++) {
        if(A[i][j] == B[i][k]) {
          A[i][j] = 0;
          break;
        }
      }
    }
  }
  for(int j = 1; j <= M; j++) {
    for(int i = 1; i <= N; i++) tmp[i] = B[i][j];
    sort(tmp + 1, tmp + N + 1);
    for(int i = 1; i <= N; i++) C[i][j] = tmp[i];
  }
  for(int i = 1; i <= N; i++)
    for(int j = 1; j <= M; j++)
      printf("%d%c", B[i][j], " \n"[j == M]);
  for(int i = 1; i <= N; i++)
    for(int j = 1; j <= M; j++)
      printf("%d%c", C[i][j], " \n"[j == M]);
  return 0;
}


Measured memory_bytes: 948