#include <bits/stdc++.h>
#pragma GCC target("avx2")
#pragma GCC optimization("O3")
#pragma GCC optimization("unroll-loops")
using namespace std;
inline bool EQ(double a, double b) { return fabs(a - b) < 1e-9; }
inline int msbp(int x) { return 31 - __builtin_clz(x); }
inline int msb(int x) { return 1 << msbp(x); }
const int INF = 0x3f3f3f3f;
struct hash_pair {
  template <class T1, class T2>
  size_t operator()(const pair<T1, T2>& p) const {
    auto hash1 = hash<T1>{}(p.first);
    auto hash2 = hash<T2>{}(p.second);
    return hash1 ^ hash2;
  }
};
const int N = 1e6 + 10;
int parent[N], rnk[N];
int find(int x) { return parent[x] = (x == parent[x] ? x : find(parent[x])); }
bool disjoint(int x, int y) { return find(x) != find(y); }
void join(int x, int y) {
  if (!disjoint(x, y)) return;
  int xPar = find(x), yPar = find(y);
  int newPar, newChild;
  if (rnk[xPar] > rnk[yPar]) {
    newPar = xPar, newChild = yPar;
  } else if (rnk[xPar] < rnk[yPar]) {
    newPar = yPar, newChild = xPar;
  } else {
    newPar = xPar, newChild = yPar;
    ++rnk[xPar];
  }
  parent[newChild] = newPar;
}
int n, m, b[N];
pair<int, int> a[N];
vector<pair<int, int>> all_vals;
map<int, vector<int>> s;
vector<int> g[N];
int d[N], dp[N];
void process_eq(vector<pair<int, int>>& cur) {
  map<int, int> val_map;
  for (auto [val, id] : cur) {
    if (val_map.count(val)) {
      join(id, val_map[val]);
    } else {
      val_map[val] = id;
    }
  }
}
void process(vector<int>& cur) {
  sort(cur.begin(), cur.end());
  for (int i = 0; i < (cur.size() - 1); ++i) {
    if (cur[i] != cur[i + 1]) {
      g[cur[i]].push_back(cur[i + 1]);
      ++d[cur[i + 1]];
    }
  }
}
signed main() {
  ios::sync_with_stdio(false);
  std::iota(parent, parent + N, 0);
  scanf("%d %d", &n, &m);
  for (int i = 0; i < (n); ++i) {
    for (int j = 0; j < (m); ++j) {
      scanf("%d", &a[i * m + j].first);
      s[a[i * m + j].first].push_back(i * m + j);
    }
  }
  vector<pair<int, int>> curm(m), curn(n);
  for (int i = 0; i < (n); ++i) {
    for (int j = 0; j < (m); ++j) curm[j] = {a[i * m + j].first, i * m + j};
    process_eq(curm);
  }
  for (int j = 0; j < (m); ++j) {
    for (int i = 0; i < (n); ++i) curn[i] = {a[i * m + j].first, i * m + j};
    process_eq(curn);
  }
  for (auto [val, ids] : s) {
    int cur = 1;
    for (int id : ids) {
      if (a[find(id)].second == 0) {
        all_vals.push_back({val, cur});
        a[find(id)].second = cur++;
      }
      a[id].second = a[find(id)].second;
    }
  }
  sort(all_vals.begin(), all_vals.end());
  map<pair<int, int>, int> id_map;
  for (int i = 0; i < (all_vals.size()); ++i) id_map[all_vals[i]] = i;
  for (int i = 0; i < (n); ++i)
    for (int j = 0; j < (m); ++j) b[i * m + j] = id_map[a[i * m + j]];
  vector<int> ccurm(m), ccurn(n);
  for (int i = 0; i < (n); ++i) {
    for (int j = 0; j < (m); ++j) ccurm[j] = b[i * m + j];
    process(ccurm);
  }
  for (int j = 0; j < (m); ++j) {
    for (int i = 0; i < (n); ++i) ccurn[i] = b[i * m + j];
    process(ccurn);
  }
  queue<int> nxt;
  for (int x = 0; x < (all_vals.size()); ++x) {
    if (d[x] == 0) {
      nxt.push(x);
      dp[x] = 1;
    }
  }
  while (!nxt.empty()) {
    int cur = nxt.front();
    nxt.pop();
    for (auto v : g[cur]) {
      dp[v] = max(dp[v], dp[cur] + 1);
      --d[v];
      if (d[v] == 0) {
        nxt.push(v);
      }
    }
  }
  for (int i = 0; i < (n); ++i) {
    for (int j = 0; j < (m); ++j) cout << dp[b[i * m + j]] << ' ';
    cout << '\n';
  }
  return 0;
}
