标签:
题意
给出一个矩阵,然后求最小矩阵,最小矩阵就是数字可以变小但是相对大小是不能改变的。
题解
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