bzoj1104: [POI2007]洪水pow
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <algorithm> 6 #define maxn 1005 7 #define maxm 1000005 8 using namespace std; 9 int m,n,ans,hi[maxm],fa[maxm],now[maxn],prep[maxm],bo[maxm]; 10 bool color[maxm]; 11 void add(int x,int y){ 12 prep[x]=now[y],now[y]=x; 13 } 14 int find(int x){ 15 if (fa[x]!=x) fa[x]=find(fa[x]); 16 return fa[x]; 17 } 18 void Connect(int x,int y){ 19 int t1,t2; 20 t1=find(x),t2=find(y); 21 if (t1==t2) return; 22 if (bo[t1]==1) fa[t2]=t1; 23 else fa[t1]=t2; 24 } 25 void connect(int x){ 26 if (x>n&&hi[x]>=hi[x-n]) Connect(x-n,x); 27 if (x<=(n*m-n)&&hi[x]>=hi[x+n]) Connect(x+n,x); 28 if ((x%n)!=1&&hi[x]>=hi[x-1]) Connect(x-1,x); 29 if ((x%n)!=0&&hi[x]>=hi[x+1]) Connect(x+1,x); 30 } 31 int main(){ 32 scanf("%d%d",&m,&n); 33 for (int i=1;i<=m;i++){ 34 for (int u,v,j=1;j<=n;j++){ 35 scanf("%d",&u),v=(i-1)*n+j; 36 if (u>0) color[v]=1,hi[v]=u; 37 else color[v]=0,hi[v]=-u; 38 } 39 } 40 memset(now,0,sizeof(now)),ans=0; 41 for (int i=1;i<=n*m;i++) add(i,hi[i]); 42 for (int i=1;i<=n*m;i++) fa[i]=i; 43 memset(bo,0,sizeof(bo)); 44 for (int i=0;i<=1000;i++){ 45 for (int u=now[i];u;u=prep[u]){ 46 connect(u); 47 } 48 for (int u=now[i];u;u=prep[u]){ 49 int v=find(u); 50 if (!bo[v]&&color[u]==1) ans++,bo[v]=1; 51 } 52 } 53 printf("%d\n",ans); 54 return 0; 55 }
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1104
做法:我们将所有的点按高度进行排序,排完序后以此加入这些点,加入时,我们用把四周比它矮的点并到一个集合当中,因为可能已有抽水机了,并完后,如果这是该市的一个区域,且它所在集合中没有抽水机,那么我们就在该集合放一架抽水机,否则跳过。注意高度相同的点。
并查集+贪心+poi思路题。