问题 E: [POI2007]洪水pow
时间限制: 5 Sec 内存限制: 128 MB
题目描述
AKD市处在一个四面环山的谷地里。最近一场大暴雨引发了洪水,AKD市全被水淹没了。Blue Mary,AKD市的市
长,召集了他的所有顾问(包括你)参加一个紧急会议。经过细致的商议之后,会议决定,调集若干巨型抽水机,
将它们放在某些被水淹的区域,而后抽干洪水。你手头有一张AKD市的地图。这张地图是边长为m*n的矩形,被划分
为m*n个1*1的小正方形。对于每个小正方形,地图上已经标注了它的海拔高度以及它是否是AKD市的一个组成部分
。地图上的所有部分都被水淹没了。并且,由于这张地图描绘的地面周围都被高山所环绕,洪水不可能自动向外排
出。显然,我们没有必要抽干那些非AKD市的区域。每个巨型抽水机可以被放在任何一个1*1正方形上。这些巨型抽
水机将持续地抽水直到这个正方形区域里的水被彻底抽干为止。当然,由连通器原理,所有能向这个格子溢水的格
子要么被抽干,要么水位被降低。每个格子能够向相邻的格子溢水,“相邻的”是指(在同一高度水平面上的射影
)有公共边。
输入
第一行是两个数m,n(1<=m,n<=1000). 以下m行,每行n个数,其绝对值表示相应格子的海拔高度;若该数为正
,表示他是AKD市的一个区域;否则就不是。请大家注意:所有格子的海拔高度其绝对值不超过1000,且可以为零.
输出
只有一行,包含一个整数,表示至少需要放置的巨型抽水机数目。
样例输入
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
样例输出
2solution: 数据很水,一开始没理解题意瞎打了个bfs过了4个点,正解应该是并查集,对于一个海拔为x的点,如果与它相邻的点中有一个海拔小于等于x的点能被抽干,那么它也可以一同被抽干;把所有点关于海拔排序,那么依次加入高度为h的点后去判断一下有没有与已经放了抽水机的点相连,如果没有则答案+1,并且在该点放上一个抽水机。 当然bfs也可以,但本蒟蒻被bfs干怕了,死活调不过去,于是就打了并查集,大佬们可以试试bfs。
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<queue> 6 using namespace std; 7 #define inf 0x3f3f3f3f 8 #define maxn 1005 9 int read() { 10 int s=0,f=1; 11 char ch=getchar(); 12 while(ch>‘9‘||ch<‘0‘) { 13 if(ch==‘-‘) { 14 f=-1; 15 } 16 ch=getchar(); 17 } 18 while(ch>=‘0‘&&ch<=‘9‘) { 19 s=(s<<1)+(s<<3)+(ch^48); 20 ch=getchar(); 21 } 22 return s*f; 23 } 24 int n,m,h[maxn][maxn],fa[maxn*maxn],cnt,ans,mv[4][2]= {1,0,-1,0,0,1,0,-1},empty[maxn*maxn]; 25 int num[maxn][maxn],tot; 26 struct oo { 27 int x,y,hei; 28 friend bool operator < (oo a,oo b) { 29 return a.hei<b.hei; 30 } 31 } s[maxn*maxn],l[maxn*maxn]; 32 inline int find(int x) { 33 return fa[x]==x?x:fa[x]=find(fa[x]); 34 } 35 void init() { 36 for(int i=0; i<=n+1; ++i) 37 h[i][0]=h[i][m+1]=inf; 38 for(int i=0; i<=m+1; ++i) 39 h[0][i]=h[n+1][i]=inf; 40 for(int i=1; i<=n*m; ++i) { 41 fa[i]=i; 42 } 43 for(int i=1; i<=n; ++i) { 44 for(int j=1; j<=m; ++j) { 45 num[i][j]=++tot; 46 } 47 } 48 } 49 int main() { 50 n=read(),m=read(); 51 init(); 52 memset(empty,0,sizeof(empty)); 53 for(int i=1; i<=n; ++i) { 54 for(int j=1; j<=m; j++) { 55 h[i][j]=read(); 56 if(h[i][j]>0) { 57 s[++cnt].x=i,s[cnt].y=j,s[cnt].hei=h[i][j]; 58 } else { 59 h[i][j]=-h[i][j]; 60 } 61 l[num[i][j]].x=i,l[num[i][j]].y=j,l[num[i][j]].hei=h[i][j]; 62 } 63 } 64 sort(l+1,l+m*n+1); 65 sort(s+1,s+cnt+1); 66 ans=0; 67 for(int i=1,k=1; i<=cnt; ++i) { 68 for(; k<=m*n&&l[k].hei<=s[i].hei; ++k) { 69 int x=l[k].x,y=l[k].y; 70 for(int j=0; j<=3; j++) { 71 int xx=x+mv[j][0],yy=y+mv[j][1]; 72 if(h[xx][yy]<=h[x][y]) { 73 empty[find(num[x][y])]|=empty[find(num[xx][yy])]; 74 fa[find(num[xx][yy])]=find(num[x][y]); 75 } 76 } 77 } 78 if(!empty[find((s[i].x-1)*m+s[i].y)]) { 79 ++ans; 80 empty[find((s[i].x-1)*m+s[i].y)]=1; 81 } 82 } 83 printf("%d\n",ans); 84 return 0; 85 }
时间: 2024-10-07 04:06:21