题目描述

Description 你手头有一张该市的地图。这张地图是边长为 m∗n 的矩形,被划分为m∗n个1∗1的小正方形。对于每个小正方形,地图上已经标注了它的海拔高度以及它是否是该市的一个组成部分。地图上的所有部分都被水淹没了。并且,由于这张地图描绘的地面周围都被高山所环绕,洪水不可能自动向外排出。显然,我们没有必要抽干那些非该市的区域。

每个巨型抽水机可以被放在任何一个1∗1正方形上。这些巨型抽水机将持续地抽水直到这个正方形区域里的水被彻底抽干为止。当然,由连通器原理,所有能向这个格子溢水的格子要么被抽干,要么水位被降低。每个格子能够向相邻的格子溢水,“相邻的”是指(在同一高度水平面上的射影)有公共边。

Input

第一行是两个数m,n(1<=m,n<=1000).

以下 m 行,每行 n 个数,其绝对值表示相应格子的海拔高度;若该数为正,表示它是该市的一个区域;否则就不是。

请大家注意:所有格子的海拔高度其绝对值不超过 1000 ,且可以为零.

Output

只有一行,包含一个整数,表示至少需要放置的巨型抽水机数目。

感谢@FlashHu 提供的翻译

样例

INPUT

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

OUTPUT

2

HINT

SOLUTION

并查集维护连通块。

其实对于题面的“连通器”原理,考场上并没有理解,导致根本看不懂样例。

其实这个模型相信大家一定见过,只是我在场上完全没有想起来。



很明显地,当右边的水位因为某种原因下降时,左边的会一同下降。

而且当i,j相邻,\(h_i\leq h_j\)时,若i点水被抽尽,j点一定也被抽尽。

所以根据这些原理,设我们的抽水机的高度为\(h_i\),那么只要相邻的点满足\(h_j\leq h_i\)即可把i,j合并。

显然本题是要我们维护连通块,考虑使用bfs或并查集实现。

我们这里使用的是并查集,枚举点向四周扩散合并。

为了方便枚举相同高度的点,我们考虑把所有点按高度升序排序。

当我们的高度相同的点枚举完,要进行一次统一合并之后再统计答案。

栗子:

数据:

1 4

3 3 -2 1

在枚举高度为3的点(左)之前,现在已有的连通块情况:

(3)(3)(2 1)

若我们在枚举完左边的3之后直接统计的话会出现情况:

(3 3)(2 1)

答案凭空多了1

因为我们做的不是bfs所以并不能像bfs那样扩散的十分彻底。这个操作就可以避免出现“连通不彻底”的情况。

本题的思维难度较高。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <map>
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-48;ch=getchar();}
return x*f;}
const int N=1010;
const int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
int n,m,sq[N][N],fa[N*N],cnt=0;
bool used[N*N];
struct NODE{int x,y,h;}q[N*N];
struct NODE2{int x,y;}nd[N*N];
inline int find (int x) {return (x==fa[x])?x:fa[x]=find(fa[x]);}
bool cmp(NODE a,NODE b){return a.h<b.h;}
int main(){
int i,j;
n=read();m=read();int ans=0;
for (i=1;i<=n;++i) for (j=1;j<=m;++j){
sq[i][j]=read();fa[++cnt]=cnt;
q[cnt].x=i;q[cnt].y=j;q[cnt].h=abs(sq[i][j]);}
sort(q+1,q+1+cnt,cmp);memset(used,0,sizeof(used));
for (i=1;i<=cnt;++i){
int x=q[i].x,y=q[i].y;
int frm=(x-1)*m+y;
for (j=0;j<4;++j){
int nx=x+dx[j],ny=y+dy[j];
// puts("******");
if ((nx<1)||(ny<1)||(nx>n)||(ny>m)) continue;
if (abs(sq[x][y])<abs(sq[nx][ny])) continue;
// printf("(%d,%d):%d,%d\n",x,y,nx,ny);
int now=(nx-1)*m+ny;
int f1=find(frm),f2=find(now);
if (f2==f1) continue;
fa[f2]=f1;used[f1]|=used[f2];
}
if (q[i].h!=q[i+1].h){
for (j=i;(q[i].h==q[j].h);--j){
int x=find((q[j].x-1)*m+q[j].y);
if (sq[q[j].x][q[j].y]<=0) continue;
if (!used[x]) {used[x]=1;ans++;}
}
}
}
printf("%d\n",ans);
return 0;
}

LG_3457_[POI2007]POW-The Flood的更多相关文章

  1. [洛谷3457][POI2007]POW-The Flood

    洛谷题目链接:[POI2007]POW-The Flood 题意翻译 Description 你手头有一张该市的地图.这张地图是边长为 m∗n 的矩形,被划分为m∗n个1∗1的小正方形.对于每个小正方 ...

  2. 洛谷P3457 [POI2007]POW-The Flood [并查集,模拟]

    题目传送门 pow 题意翻译 Description 你手头有一张该市的地图.这张地图是边长为 m∗n 的矩形,被划分为m∗n个1∗1的小正方形.对于每个小正方形,地图上已经标注了它的海拔高度以及它是 ...

  3. [POI2007]洪水pow 题解

    [POI2007]洪水pow 时间限制: 5 Sec  内存限制: 128 MB 题目描述 AKD市处在一个四面环山的谷地里.最近一场大暴雨引发了洪水,AKD市全被水淹没了.Blue Mary,AKD ...

  4. [POI2007]POW-The Flood(并查集)

    [POI2007]POW-The Flood Description AKD 市处在一个四面环山的谷地里.最近一场大暴雨引发了洪水,AKD 市全被水淹没了.Blue Mary,AKD 市的市长,召集了 ...

  5. P3457 [POI2007]POW-The Flood

    题意翻译 Description 你手头有一张该市的地图.这张地图是边长为 m∗n 的矩形,被划分为m∗n个1∗1的小正方形.对于每个小正方形,地图上已经标注了它的海拔高度以及它是否是该市的一个组成部 ...

  6. bzoj1104: [POI2007]洪水pow

    #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #i ...

  7. 【BZOJ】1104: [POI2007]洪水pow

    题意 给一个\(n * m(1 \le n, m \le 1000)\)的矩阵,如果\(a_{i, j}\)为正表示城市.\(|a_{i, j}|(|a_{i, j}| \le 1000)\)是格子\ ...

  8. [POI2007]洪水pow 并查集

    我们先得出一个结论:水泵要建在城市上.因为如果在非城市上建能把其他一些城市抽干,那么在城市上建也是一个效果(自己画图感性理解一下) 然后我们明白抽水的条件:周围的高度要>=自身的高度,这样会抽完 ...

  9. Luogu345: [POI2007]POW-The Flood

    题意 见luogu Sol 贪心 从小到大枚举高度,把小于等于这一高度的相邻格子用并查集合并 那么这个集合内的所有格子都一定可以由这个集合内的一个最低点抽完水 那么合并之后(一定要在合并之后) 判断这 ...

随机推荐

  1. 可能对Flutter应用程序开发有用的代码/库/专有技术列表

    当我开始使用Flutter实施该应用程序时,我开始担心“如何最好地编写?”以及“如何使其更好地放置?”. 在这种情况下,您将需要参考GitHub上发布的代码和应用程​​序. 因此,我收集了似乎对Flu ...

  2. Thinkcmf截取内容长度

    例1: {$vo.post_title|msubstr=0,10} 截取标题,msubstr=0,10,数字表示截取的字符串长度,显示省略号,但无论长度是否超过截取的长度都会出现省略号: 例2: {$ ...

  3. 分糖果(BFS)

    题目描述 童年的我们,将和朋友分享美好的事物作为自己的快乐.这天,C小朋友得到了糖果,将要把这些糖果分给要好的朋友们.已知糖果从一个人传给另一个人需要1秒的时间,同一个小朋友不会重复接受糖果.由于糖果 ...

  4. SOA架构设计分析

    SOA(Service-Oriented Architecture,面向服务的架构)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和契约联系起来. S ...

  5. session和token区别

    分布式系统认证/授权目前分布式系统存在两种常用的认证授权方式:分布式session和token 1.session的概念 session中存放登录用户的个人信息,创建session时,随机生成一个se ...

  6. matlab代码学习_2018-7-28

    1.核范数||A|| * 是指矩阵奇异值的和,英文称呼叫Nuclear Norm.matlab code:[s, u, v] = svd(A); nulear_norm = sum(diag(s)); ...

  7. Maven打包时报Failed to execute goal org.apache.maven.plugins:maven-war-plugin:解决方案

    问题现象: 用Maven打包时,报Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.2:war错误. 原因分析: 打 ...

  8. Asexual inheritance

    Asexual inheritance 1,2分别是两种基因型 N1,N2是两种基因型的亲代个数,Wt是t代后每一个每一个基因型的后代数 N1’,N2’是t代后1,2,基因型的个体数 the prop ...

  9. kotlin 单例模式

    class Single{ companion object { val instance:Single by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZE ...

  10. Canal —— 基本概念及使用

    参考文档 开源数据同步神器--canal [若泽大数据]大数据之实时数据源同步中间件--生产上Canal与Maxwell颠峰对决