[bzoj1104][并查集][贪心]洪水pow

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Rose_max/article/details/82905300

Description

AKD市处在一个四面环山的谷地里。最近一场大暴雨引发了洪水,AKD市全被水淹没了。Blue Mary,AKD市的市
长,召集了他的所有顾问(包括你)参加一个紧急会议。经过细致的商议之后,会议决定,调集若干巨型抽水机,
将它们放在某些被水淹的区域,而后抽干洪水。你手头有一张AKD市的地图。这张地图是边长为mn的矩形,被划分
为m
n个11的小正方形。对于每个小正方形,地图上已经标注了它的海拔高度以及它是否是AKD市的一个组成部分
。地图上的所有部分都被水淹没了。并且,由于这张地图描绘的地面周围都被高山所环绕,洪水不可能自动向外排
出。显然,我们没有必要抽干那些非AKD市的区域。每个巨型抽水机可以被放在任何一个1
1正方形上。这些巨型抽
水机将持续地抽水直到这个正方形区域里的水被彻底抽干为止。当然,由连通器原理,所有能向这个格子溢水的格
子要么被抽干,要么水位被降低。每个格子能够向相邻的格子溢水,“相邻的”是指(在同一高度水平面上的射影 )有公共边。

Input

第一行是两个数m,n(1<=m,n<=1000). 以下m行,每行n个数,其绝对值表示相应格子的海拔高度;若该数为正
,表示他是AKD市的一个区域;否则就不是。请大家注意:所有格子的海拔高度其绝对值不超过1000,且可以为零.

Output

只有一行,包含一个整数,表示至少需要放置的巨型抽水机数目。

Sample Input

6 9

-2 -2 -1 -1 -2 -2 -2 -12 -3

-2 1 -1 2 -8 -12 2 -12 -12

-5 3 1 1 -12 4 -6 2 -2

-5 -2 -2 2 -12 -3 4 -3 -1

-5 -6 -2 2 -12 5 6 2 -1

-4 -8 -8 -10 -12 -8 -6 -6 -4

Sample Output

2

题解

把海拔排序
从小到大扫
扫到一个点的时候,看他周围四个点
如果有一个点的海拔比他低 就让他和这个点的连通块合并
因为只要他的连通块里有一个抽水机他就可以被抽走了…
扫完之后判一下他所在的连通块,如果没有抽水机要给他一个抽水机
前提是他得是市内的
海拔高度相同的,要先全部合并完
因为他们是可以利用同一台抽水机的,完全没必要再开几台抽水机

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#define LL long long
#define mp(x,y) make_pair(x,y)
using namespace std;
inline int read()
{
	int f=1,x=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void write(int x)
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
}
inline void print(int x){write(x);printf(" ");}
const int dx[4]={-1,0,1,0};
const int dy[4]={0,-1,0,1};
int n,m,mp[1005][1005];
int pt(int x,int y){return (x-1)*m+y;}
struct node
{
	int x,y,dep;
}w[1005*1005];
bool cmp(node n1,node n2){return abs(n1.dep)<abs(n2.dep);}
bool ok[1005*1005];
int fa[1005*1005];
int findfa(int x){return fa[x]==x?fa[x]:fa[x]=findfa(fa[x]);}
int main()
{
	n=read();m=read();
	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)w[pt(i,j)].dep=mp[i][j]=read(),w[pt(i,j)].x=i,w[pt(i,j)].y=j,fa[pt(i,j)]=pt(i,j);
	sort(w+1,w+1+n*m,cmp);
	int ans=0,nxt;
	for(int i=1;i<=n*m;i=nxt)
	{
		nxt=i;
		while(nxt<n*m&&abs(w[nxt+1].dep)==abs(w[i].dep))nxt++;
		for(int j=i;j<=nxt;j++)
			for(int k=0;k<=3;k++)
			{
				int u=w[j].x+dx[k],v=w[j].y+dy[k];
				if(u<1||u>n||v<1||v>m)continue;
				if(abs(mp[u][v])<=abs(w[j].dep))
				{
					int p=findfa(pt(u,v)),q=findfa(pt(w[j].x,w[j].y));
					if(p!=q)fa[q]=p,ok[p]|=ok[q];
				}
			}
		for(int j=i;j<=nxt;j++)if(w[j].dep>0)
		{
			int p=findfa(pt(w[j].x,w[j].y));
			if(!ok[p])ok[p]=1,ans++;
		}nxt++;
	}
	printf("%d\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Rose_max/article/details/82905300