#include <bits/stdc++.h>
using namespace std;
inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T>
inline string toString(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}
int n, m;
int val[2000005];
int deg[2000005];
map<int, int> bt;
vector<vector<int> > g(2000005);
vector<vector<pair<int, int> > > row(2000005);
vector<vector<pair<int, int> > > col(2000005);
int res[1001][1001];
int DP[2000005];
map<pair<int, int>, int> mp;
bool vis[2000005];
class DSU {
 private:
  vector<int> p, rank, setSize;
  int numSets;

 public:
  DSU(int N) {
    setSize.assign(N, 1);
    numSets = N;
    rank.assign(N, 0);
    p.assign(N, 0);
    for (int i = 0; i < N; i++) p[i] = i;
  }
  int findSet(int i) { return (p[i] == i) ? i : (p[i] = findSet(p[i])); }
  bool isSameSet(int i, int j) { return findSet(i) == findSet(j); }
  void unionSet(int i, int j) {
    if (!isSameSet(i, j)) {
      numSets--;
      int x = findSet(i), y = findSet(j);
      if (rank[x] > rank[y]) {
        p[y] = x;
        setSize[x] += setSize[y];
      } else {
        p[x] = y;
        setSize[y] += setSize[x];
        if (rank[x] == rank[y]) rank[y]++;
      }
    }
  }
  int numDisjointSets() { return numSets; }
  int sizeOfSet(int i) { return setSize[findSet(i)]; }
};
void dfs(int u) {
  if (vis[u]) return;
  vis[u] = 1;
  DP[u] = 1;
  for (int j = 0; j < ((int)(g[u].size())); ++j) {
    int v = g[u][j];
    dfs(v);
    DP[u] = max(DP[u], 1 + DP[v]);
  }
}
int main() {
  scanf("%d %d", &n, &m);
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < m; ++j) scanf("%d", &mp[pair<int, int>(i, j)]);
  memset(vis, 0, sizeof(vis));
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      row[i].push_back(make_pair(mp[pair<int, int>(i, j)], i * m + j));
      col[j].push_back(make_pair(mp[pair<int, int>(i, j)], i * m + j));
    }
  }
  DSU dsu(n * m);
  for (int i = 0; i < ((int)(row.size())); ++i)
    sort(row[i].begin(), row[i].end());
  for (int j = 0; j < ((int)(col.size())); ++j)
    sort(col[j].begin(), col[j].end());
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      vector<pair<int, int> >::iterator it =
          lower_bound(row[i].begin(), row[i].end(),
                      make_pair(mp[pair<int, int>(i, j)], i * m + j + 1));
      if (it != row[i].end()) {
        if (it->first == mp[pair<int, int>(i, j)]) {
          dsu.unionSet(i * m + j, it->second);
        }
      }
      it = lower_bound(col[j].begin(), col[j].end(),
                       make_pair(mp[pair<int, int>(i, j)], i * m + j + 1));
      if (it != col[j].end()) {
        if (it->first == mp[pair<int, int>(i, j)]) {
          dsu.unionSet(i * m + j, it->second);
        }
      }
    }
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      vector<pair<int, int> >::iterator it =
          lower_bound(row[i].begin(), row[i].end(),
                      make_pair(mp[pair<int, int>(i, j)], 1 << 30));
      if (it != row[i].end()) {
        g[dsu.findSet(it->second)].push_back(dsu.findSet(i * m + j));
      }
      it = lower_bound(col[j].begin(), col[j].end(),
                       make_pair(mp[pair<int, int>(i, j)], 1 << 30));
      if (it != col[j].end()) {
        g[dsu.findSet(it->second)].push_back(dsu.findSet(i * m + j));
      }
    }
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      if (!deg[dsu.findSet(i * m + j)]) dfs(dsu.findSet(i * m + j));
    }
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      printf("%d ", DP[dsu.findSet(i * m + j)]);
    }
    puts("");
  }
}
