您的位置:首页 > 其它

[BZOJ]1104: [POI2007]洪水pow

2017-06-30 15:01 337 查看
Description

  AKD市处在一个四面环山的谷地里。最近一场大暴雨引发了洪水,AKD市全被水淹没了。Blue Mary,AKD市的市长,召集了他的所有顾问(包括你)参加一个紧急会议。经过细致的商议之后,会议决定,调集若干巨型抽水机,将它们放在某些被水淹的区域,而后抽干洪水。你手头有一张AKD市的地图。这张地图是边长为m*n的矩形,被划分为m*n个1*1的小正方形。对于每个小正方形,地图上已经标注了它的海拔高度以及它是否是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

对于一个海拔为x的点,如果与它相邻的点中有一个海拔小于等于x的点能被抽干,那么它也可以一同被抽干。很容易就能想到并查集,我们把一堆可以用一个抽水机解决的点连在一起,最后看要用多少个就好了。

#include <cstdio>
#include <algorithm>
using namespace std;
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline int read(void)
{
int a=0,f=1;static char c;
while((c=tc())<'0'||c>'9')c=='-'?f=-1:0;
while(c>='0'&&c<='9')
a=a*10+c-'0',c=tc();
return a*f;
}
int n,m,tot,cnt,f[1000001],map[1002][1002],ans,dx[]={1,-1,0,0},dy[]={0,0,1,-1},x,y,_x,_y,t,o;
struct Y
{
int x,y,h;
bool operator <(const Y&a) const
{
return h<a.h;
}
}city[1000001],s[1000001];
char have[1000001];
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
int main(void)
{
register int i,j,l;
n=read(),m=read();
for (i=1;i<=n;++i)
for (j=1;j<=m;++j)
f[(i-1)*m+j]=(i-1)*m+j,x=read(),x>0?(city[++cnt].x=i,city[cnt].y=j,city[cnt].h=x,s[++tot].x=i,s[tot].y=j,s[tot].h=x,map[i][j]=x):(s[++tot].x=i,s[tot].y=j,s[tot].h=-x,map[i][j]=-x);
for (i=0;i<=n+1;i++)
map[i][0]=map[i][m+1]=2e9;
for (i=0;i<=m+1;i++)
map[0][i]=map[n+1][i]=2e9;
sort(city+1,city+cnt+1),sort(s+1,s+tot+1);  //按海拔从小到大进行操作
for (i=1,j=1;i<=cnt;++i)
{
for (;j<=n*m&&s[j].h<=city[i].h;++j)
{
x=s[j].x,y=s[j].y,t=(x-1)*m+y;
for (l=0;l<4;++l)
{
_x=x+dx[l],_y=y+dy[l],o=(_x-1)*m+_y;
if(map[_x][_y]<=map[x][y])
have[find(t)]|=have[find(o)],f[find(o)]=find(t);//以海拔较高的点作为父节点,这一过程中城市节点的海拔最高,能便于之后打have标记
}
}
if(!have[find((city[i].x-1)*m+city[i].y)])
++ans,have[find((city[i].x-1)*m+city[i].y)]=1;//对以这个城市节点为父节点的并查集打上have标记
}
printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: