题目链接: http://codeforces.com/problemset/problem/650/C
---------------------------------------------------------------------------------------------------------
首先要知道的是这题原本相同的数最后是可以不同的
然后主要是要考虑到$Z$字形的数据 ($a$代表某相同数字 $x$代表其他数字)
$aax$
$xaa$
这种情况下第一行第一个和第二行第三个是必须相同的
如果只是对行和列进行简单的十字型的判断的话这两个位置最终的数字很有可能不同
所以我们要对行和列的当前最大数的最小值进行维护 然后就是写一个并查集了
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 const int N = 1e6 + 10; 8 vector <int> a[N], b[N]; 9 int s[N], num[N << 1], fa[N]; 10 int n, m, len, ans; 11 int findf(int x) 12 { 13 if(fa[x] != x) 14 fa[x] = findf(fa[x]); 15 return fa[x]; 16 } 17 void merge(int x, int y) 18 { 19 int tx = findf(x), ty = findf(y); 20 if(tx != ty) 21 { 22 if(num[tx] >= num[ty]) 23 fa[ty] = tx; 24 else 25 fa[tx] = ty; 26 } 27 } 28 int main() 29 { 30 int x, y; 31 scanf("%d%d", &n, &m); 32 for(int i = 0; i < n; ++i) 33 for(int j = 0; j < m; ++j) 34 { 35 scanf("%d", &x); 36 a[i].push_back(x); 37 s[len++] = x; 38 } 39 sort(s, s + len); 40 len = unique(s, s + len) - s; 41 for(int i = 0; i < n; ++i) 42 for(int j = 0; j < m; ++j) 43 { 44 a[i][j] = lower_bound(s, s + len, a[i][j]) - s; 45 b[a[i][j]].push_back(i * m + j); 46 } 47 for(int i = 0; i < n + m; ++i) 48 fa[i] = i; 49 for(int i = 0; i < len; ++i) 50 { 51 for(int j = 0, sz = b[i].size(); j < sz; ++j) 52 { 53 x = b[i][j] / m; 54 y = b[i][j] % m; 55 merge(x, n + y); 56 } 57 for(int j = 0, sz = b[i].size(); j < sz; ++j) 58 { 59 x = b[i][j] / m; 60 y = b[i][j] % m; 61 a[x][y] = num[findf(x)] + 1; 62 } 63 for(int j = 0, sz = b[i].size(); j < sz; ++j) 64 { 65 x = b[i][j] / m; 66 y = b[i][j] % m; 67 num[x] = max(num[x], a[x][y]); 68 num[n + y] = max(num[n + y], a[x][y]); 69 fa[x] = x; 70 fa[n + y] = n + y; 71 } 72 } 73 for(int i = 0; i < n; ++i) 74 for(int j = 0; j < m; ++j) 75 printf("%d%c", a[i][j], (j == m - 1 ? ' ' : ' ')); 76 return 0; 77 }