码迷,mamicode.com
首页 > 其他好文 > 详细

CDOJ 1338 郭大侠与英雄学院 (并查集) - xgtao -

时间:2016-08-03 10:32:23      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:

郭大侠与英雄学院

 

题意

给出一个矩阵,然后求最小矩阵,最小矩阵就是数字可以变小但是相对大小是不能改变的。

 

题解

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!