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
",ans);
54     return 0;
55 }
View Code

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1104

做法:我们将所有的点按高度进行排序,排完序后以此加入这些点,加入时,我们用把四周比它矮的点并到一个集合当中,因为可能已有抽水机了,并完后,如果这是该市的一个区域,且它所在集合中没有抽水机,那么我们就在该集合放一架抽水机,否则跳过。注意高度相同的点。

并查集+贪心+poi思路题。

原文地址:https://www.cnblogs.com/OYzx/p/5572422.html