标签:
题意
给出一个矩阵,然后求最小矩阵,最小矩阵就是数字可以变小但是相对大小是不能改变的。
题解
1.分析最基本的思路,假设每个数字都不同,就把记录数字的位置和权值,再把每个数字根据权值从小到大排一次序,这个位置就为max(这一行的最大值,这一列的最大值)+1.
2.但是出现了同一行同一列相同数字怎么办呢?就用并查集把同行同列的相同的数都给用一个id表示出来,再找出每一相同的数各自的每一行每一列综合起来的最大值maxi+1,最后用maxi+1来更新每一相同的数各自的每一行每一列的最大值。
代码
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 1000010; struct node{ int x,y,u; bool operator < (const node& rhs)const{return u < rhs.u;} }A[N]; int X[N],Y[N],Posx[N],Posy[N],n,m,fa[N],ans[N]; int find(int x){ return fa[x] == x ? x : fa[x] = find(fa[x]); } void Uni(int x,int y){ int fx = find(x),fy = find(y); if(fx != fy)fa[fx] = fy; } int main(){ scanf("%d%d",&n,&m); for(int i = 0;i < n*m;++i){ fa[i] = i; scanf("%d",&A[i].u); A[i].x = i/m,A[i].y = i%m; } sort(A,A+m*n); int pre = -1; for(int i = 0;i < m*n;++i){ if(i != n*m-1 && A[i].u == A[i+1].u)continue; for(int k = pre+1;k <= i;++k){ int id = A[k].x*m+A[k].y; Posx[A[k].x] = id,Posy[A[k].y] = id; } for(int k = pre+1;k <= i;++k){ int id = A[k].x*m+A[k].y; Uni(Posx[A[k].x],id); Uni(Posy[A[k].y],id); } for(int k = pre+1;k <= i;++k){ int id = A[k].x*m+A[k].y; int pa = find(id); ans[pa] = max(ans[pa],max(X[A[k].x],Y[A[k].y])+1); } for(int k = pre+1;k <= i;++k){ int id = A[k].x*m+A[k].y; X[A[k].x] = max(X[A[k].x],ans[find(id)]); Y[A[k].y] = max(Y[A[k].y],ans[find(id)]); } pre = i; } for(int i = 0;i < m*n;++i){ printf("%d ",ans[find(i)]); if(i%m == m-1)puts(""); } return 0; }
CDOJ 1338 郭大侠与英雄学院 (并查集) - xgtao -
标签:
原文地址:http://www.cnblogs.com/xgtao984/p/5731461.html