cdoj1338郭大侠与英雄学院
地址:http://acm.uestc.edu.cn/#/problem/show/1338
思路:
郭大侠与英雄学院
Time Limit: 6000/2000MS (Java/Others) Memory Limit: 225535/225535KB (Java/Others)
大部分的人类,在这个时代里都拥有名为“个性”的力量,但有力量之人却不一定都属於正义的一方。只要邪恶出现的地方,必定会有英雄挺身而出拯救众人。一名天生没有力量的少年——郭大侠从小就憧憬一位顶尖英雄,而他的梦想就是成为伟大的英雄,可是,没有力量的他能实现自己的梦想吗?虽然困难重重,少年却依旧不放弃,朝著自己的目标勇往前进!
……
尽管郭大侠没有个性,但是郭大侠的确是一个拥有超强意志的“英雄”。
所谓的英雄,便是能够在大家无动于衷的时候,挺身而出!
今天,郭大侠出现了!
郭大侠面对一个n∗mn∗m的矩阵,每个矩阵的每一个位置都有一个怪物。
郭大侠为了更好的击败他们,他的第一个任务就是分析怪物的战斗力。
为了简化自己分析时候的计算,郭大侠需要得到另外一个n∗mn∗m的矩阵。
这个矩阵满足以下要求:
1.这个新矩阵每一行,每一列中的大小关系和原矩阵一样。
2.这个新矩阵的最小值应该尽量小;保证最小值最小的情况下,使得第二小的值尽量小……使得最大值尽量小。
现在郭大侠特别忙,请你帮助郭大侠输出这个矩阵吧!
Input
第一行n,m表示矩阵的大小
接下来n行,每行m个整数,表示怪物的战斗力
保证:
1<=n∗m<=10000001<=n∗m<=1000000
怪物的战斗力是int范围内的数。
Output
输出一个新的矩阵~
新的矩阵中,最小的数至少为1哦。
Sample input and output
Sample Input | Sample Output |
---|---|
3 3 1 2 3 4 5 6 7 8 9 |
1 2 3 2 3 4 3 4 5 |
2 2 1 4 3 2 |
1 2 2 1 |
思路:
最基本的思路是对所有数排个序,然后一个一个填就好了,然而因为同行同列中有相同的数就麻烦了。
所以每次把同行同列中的的所有相同的的数拖进同一个并查集,用并查集来维护相同数应该放的值
就这样一层一层的合并,直到填完。。
不过输出的时候就要用并查集里记录的那个答案来输出。。。(话说这题想了我一万年,,,,
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cmath> 5 #include <cstring> 6 #include <queue> 7 #include <stack> 8 #include <map> 9 #include <vector> 10 #include <cstdlib> 11 #include <string> 12 13 #define PI acos((double)-1) 14 #define E exp(double(1)) 15 const int MAX=1e6+10; 16 using namespace std; 17 struct node 18 { 19 int v,x,y; 20 }a[MAX]; 21 int ans[MAX],xmax[MAX],ymax[MAX],hx[MAX],hy[MAX]; 22 int root[MAX]; 23 int fd(int x) 24 { 25 return x!=root[x]?root[x]=fd(root[x]):x; 26 } 27 void join(int x,int y) 28 { 29 int a=fd(x),b=fd(y); 30 if(a!=b)root[a]=b; 31 } 32 bool cmp(struct node c,struct node b) 33 { 34 return c.v<b.v; 35 } 36 int main (void) 37 { 38 int n,m; 39 cin>>n>>m; 40 for(int i=1;i<=n;i++) 41 for(int j=1;j<=m;j++) 42 { 43 scanf("%d",&a[(i-1)*m+j].v); 44 a[(i-1)*m+j].x=i;a[(i-1)*m+j].y=j; 45 } 46 sort(a+1,a+n*m+1,cmp); 47 memset(xmax,0,sizeof(xmax)); 48 memset(ymax,0,sizeof(ymax));//全部设为0, 49 memset(ans,0,sizeof(ans)); 50 int same=1;//记录相同元素 51 for(int i=1;i<=n*m;i++) 52 root[i]=i; 53 for(int i=1;i<=n*m;i++) 54 { 55 if(i!=n*m && a[i].v==a[i+1].v) 56 continue; 57 for(int j=same;j<=i;j++) 58 { 59 hx[a[j].x]=hy[a[j].y]=(a[j].x-1)*m+a[j].y; 60 } 61 for(int j=same;j<=i;j++) 62 { 63 join(hx[a[j].x],(a[j].x-1)*m+a[j].y); 64 join(hy[a[j].y],(a[j].x-1)*m+a[j].y); 65 } 66 for(int j=same;j<=i;j++) 67 { 68 int x = a[j].x,y=a[j].y; 69 int rt = fd((a[j].x-1)*m+a[j].y); 70 ans[rt]=max(ans[rt],max(xmax[x],ymax[y])+1); 71 } 72 for(int j=same;j<=i;j++) 73 { 74 int x = a[j].x,y=a[j].y; 75 xmax[x]=max(xmax[x],ans[fd((a[j].x-1)*m+a[j].y)]); 76 ymax[y]=max(ymax[y],ans[fd((a[j].x-1)*m+a[j].y)]); 77 } 78 same=i+1; 79 } 80 for(int i=1;i<=n*m;i++) 81 { 82 if(i%m==0) 83 printf("%d \n",ans[fd(i)]); 84 else 85 printf("%d ",ans[fd(i)]); 86 } 87 return 0; 88 }
作者:weeping
出处:www.cnblogs.com/weeping/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。