#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;   }