[POI2007]POW-The Flood

题目描述

给定一张地势图,所有的点都被水淹没,现在有一些关键点,要求放最少的水泵使所有关键点的水都被抽干

输入输出格式

输入格式:

In the first line of the standard input there are two integers  and , separated by a single space,. The following  lines contain the description of the map. The 'th linedescribes the 'th row ofunitary squares in the map. It contains  integers , separated by single spaces,.

The number  describes the 'th square of the ![](http://main.edu.pl/images/OI14/pow-en-tex.14.pn

输出格式:

Your programme should write out one integer to the standard output - the minimum number of pumpsneeded to drain Byteburg.

输入输出样例

输入样例#1:
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
输出样例#1:
2
我们首先考虑如果在格子 a 修建一个抽水机,在什么情况下格子 b 的水也可以被抽干。
我们可以发现当且仅当存在一条从 a 到 b 的路径,中间经过的抽水机(包括 a)的高度都不大于 b 的高度。
即h[b]>=max(h[i])
因此我们可以考虑把所有格子的高度从小到大排序,我们把每一个格子建成一个集合。
然后按照海拔高度从小到大扫描格子,对于当前的格子 i,我们找到所有与 i 相邻并且海拔高度不大于格子 i 的格子,
我们发现如果这些格子中的任意一个洪水要是被解决了,那么格子 i 的洪水也可以被解决,所以我们合并这些格子。
对于当前的格子 i,如果它必须被清理且与它相邻的格子集合中没有任何一个被清理,我们则把这个集合的清理状态标记为真,然后答案加 1。
集合和每个格子是否被清理用并查集来维护就可以了。
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 struct node
 7 {
 8     int s,x,y;
 9 } city[1000001],maze[100001];
10 pair<int,int> set[1001][1001];
11 int dx[5]={0,1,-1,0,0};
12 int dy[5]={0,0,0,1,-1};
13 int n,m,a[1001][1001],tot,cnt,vis[1001][1001],ans;
14 bool cmp(node a,node b)
15 {
16     return (a.s<b.s);
17 }
18 pair<int,int> find(pair<int,int> x)
19 {
20     if (set[x.first][x.second]!=x) set[x.first][x.second]=find(set[x.first][x.second]);
21     return set[x.first][x.second];
22 }
23 void union_set(pair<int,int> x,pair<int,int> y)
24 {
25     x=find(x),y=find(y);
26         set[x.first][x.second]=y;
27         vis[y.first][y.second]|=vis[x.first][x.second];
28 }
29 void exam(int x,int y)
30 {
31     for(int i=1;i<=4;i++)
32     {
33         int tx=x+dx[i], ty=y+dy[i];
34         if(tx<=0||ty<=0||tx>m||ty>n) continue;
35         if(a[tx][ty]>a[x][y]) continue;
36         union_set(make_pair(x, y), make_pair(tx, ty));
37     }
38 }
39 int main()
40 {
41     int i,j;
42     cin>>n>>m;
43     for (i=1; i<=n; i++)
44     {
45         for (j=1; j<=m; j++)
46         {
47             scanf("%d",&a[i][j]);
48             if (a[i][j]<=0)
49             {
50                 a[i][j]=-a[i][j];
51             }
52             else
53             {
54                 city[++tot]=(node){a[i][j],i,j};
55             }
56             maze[++cnt]=(node){a[i][j],i,j};
57             set[i][j]=make_pair(i,j);
58         }
59     }
60     sort(maze+1,maze+cnt+1,cmp);
61     sort(city+1,city+tot+1,cmp);
62     for (i=1; i<=tot; i++)
63     {
64         for (j=1; j<=cnt,city[i].s>=maze[j].s; j++)
65         {
66             exam(maze[j].x,maze[j].y);
67             pair<int,int> x=find(make_pair(city[i].x,city[i].y));
68             if (vis[x.first][x.second]==0)
69             {
70                 ans++;
71                 vis[x.first][x.second]=1;
72             }
73         }
74     }
75     cout<<ans;
76 }

 

posted @ 2017-07-22 14:14  Z-Y-Y-S  阅读(387)  评论(0编辑  收藏  举报