问题 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
样例输出
2
提示
其实能够证明,放在城市一定最优。。从最低的地点开始处理,因为抽水机建的越低一定最优。用一个p[]数组记录这个点是不是已经能被抽水了。在遍历的时候,找这个点四周已被标记的点(说白了就是比他低的),合并为自己的父亲,看能否连上。在每搜完一个高度以后,找刚刚遍历的点,看是否有没联通的城市,如果有那他就得建抽水机了。(不能最后判断,不然高地势会把连不上的低地势连上的)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int n,m,cnt,ans; struct city { int h,id; friend bool operator <( city a, city b){return a.h<b.h;} }a[1000005]; int f[1000005],vis[10000005],id[1005][1005],v[1000005]; int p[1000005],t2[4][2]={{-1,0,},{0,-1,},{0,1,},{1,0,},}; int find(int x) { if(f[x]!=x)f[x]=find(f[x]); return f[x]; } void get(int g) { int k=a[g].id;int x=(k-1)/m+1,y=(k-1)%m+1; for(int i=0;i<4;i++) { int x1=x+t2[i][0],y1=y+t2[i][1]; if(x1>=1&&x1<=n&&y1>=1&&y1<=m) { int l=id[x1][y1]; if(vis[l]) { int fx=find(l); p[k]=(p[k]||p[fx]); f[fx]=find(k); } } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&a[++cnt].h); id[i][j]=cnt; if(a[cnt].h>0)v[cnt]=1; else a[cnt].h=abs(a[cnt].h); //v[i][j]=a[cnt].h; a[cnt].id=cnt; f[cnt]=cnt; } sort(a+1,a+cnt+1); int last=1; for(int i=1;i<=cnt;i++) { get(i); vis[a[i].id]=1; if(a[i+1].h!=a[i].h) { for(int j=last;j<=i;j++) { int k=a[j].id; if(v[k]&&!p[find(k)]) { ans++; p[find(k)]=1; } } last=i+1; } } cout<<ans; }