Codeforces 650C Table Compression (并查集)
题意:M×N的矩阵 让你保持每行每列的大小对应关系不变,将矩阵重写,重写后的最大值最小。
思路:离散化思想+并查集,详见代码
好题!
1 #include <iostream> 2 #include <string.h> 3 #include <stdio.h> 4 #include <algorithm> 5 #include <cmath> 6 #include <cstdlib> 7 #include <bits/stdc++.h> 8 using namespace std; 9 #define clc(a,b) memset(a,b,sizeof(a)) 10 const double pi=acos(-1); 11 const int maxn=1000010; 12 int k,n,m,tot,i,j; 13 struct data { 14 int r,c,v,id; 15 } p[maxn]; 16 bool cmp(const data &a,const data &b) { 17 return a.v<b.v; 18 } 19 int f[maxn],X[maxn],Y[maxn],x[maxn],y[maxn],ans[maxn],tmp[maxn]; 20 21 int F(int a) { 22 return a==f[a]?f[a]:f[a]=F(f[a]); 23 } 24 25 int main() { 26 //freopen("in.txt","r",stdin); 27 scanf("%d%d",&n,&m); 28 tot=0; 29 clc(tmp,0); 30 clc(f,-1); 31 for( i=1; i<=n; i++) { 32 for( j=1; j<=m; j++) { 33 scanf("%d",&p[++tot].v); 34 p[tot].r=i,p[tot].c=j; 35 p[tot].id=tot; 36 f[tot]=tot; 37 } 38 } 39 sort(p+1,p+1+tot,cmp); 40 for(i=1; i<=tot; i=j) { 41 for(j=i; p[i].v==p[j].v; j++);//每次只处理相同元素 42 for(k=i; k<j; k++) {//每行每列并查集统计,归并到一个集合 43 int r=p[k].r,c=p[k].c; 44 if(!x[r]) x[r]=k; 45 else 46 f[F(k)]=F(x[r]); 47 if(!y[c]) y[c]=k; 48 else 49 f[F(k)]=F(y[c]); 50 } 51 for(k=i; k<j; k++) {//当前值的改变值 应该是该元素所在行或列 前一个填入的值再加一 52 int q=F(k); 53 tmp[q]=max(tmp[q],max(X[p[k].r],Y[p[k].c])+1); 54 } 55 for(k=i; k<j; k++) {//X Y数组维护行和列的最大填入值 56 x[p[k].r]=y[p[k].c]=0; 57 X[p[k].r]=Y[p[k].c]=ans[p[k].id]=tmp[F(k)]; 58 } 59 } 60 for(i=1; i<=tot; i++) { 61 if(i%m==1) 62 printf("%d",ans[i]); 63 else 64 printf(" %d",ans[i]); 65 if(i%m==0) 66 printf("\n"); 67 } 68 return 0; 69 }