洛谷P3457 [POI2007]POW-The Flood

题目链接

题意翻译

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

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

Input

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

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

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

Output

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

题目描述

Byteburg, the capital of Byteotia, is a picturesque city situated in a valley in the midst of mountains. Unfortunately, recent heavy rainfall has caused a flood - all the Byteburg is now completely under water. Byteasar, the king of Byteotia, has summoned his most enlightened advisors, including you, to a council. After long deliberations the council agreed to bring a few pumps, set them up in the flooded area and drain Byteburg.

The king has asked you to determine the minimum number of pumps sufficing to drain the city.

You are provided with a map of the city and the valley it is situated in. The map is in the shape of a m×nm\times nm×n rectangle, divided into unitary squares. For each such square the map tells its height above sea level and alsowhether it is a part of Byteburg or not. The whole area depicted in the map is under water. Furthermore, it issurrounded by much higher mountains, making the outflow of water impossible. Obviously, there is no needto drain the area that does not belong to Byteburg.

Each pump can be placed in any unitary square depicted in the map. The pump will be drawing thewater until its square is completely drained. Of course, the communicating tubes principle makes its work, so draining one square results in lowering the water level or complete draining of those squares from which the water can flow down to the one with the pump. Water can flow only between squares with a common side (or, more exact, squares whose projections onto horizontal plane have a common side, since the squares may be at different level). Apart from that, the water obviously only flows down.
Task

Write a programme that:

reads description of the map from the standard input,

determines the minimum number of pumps needed to drain whole Byteburg,
writes out the outcome to the standard output.

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

输入输出格式

输入格式:

In the first line of the standard input there are two integers mmm and nnn , separated by a single space, 1≤n,m≤1 0001 \le n, m \le 1\ 0001≤n,m≤1 000 . The following mmm lines contain the description of the map. The (i+1)(i+1)(i+1) ‘th line describes the iii ‘th row of unitary squares in the map. It contains nnn integers xi,1,xi,2,…,xinx_{i,1}, x_{i,2}, …, x_{i_n}xi,1​,xi,2​,…,xin​​ , separated by single spaces,−1 000≤xi,j≤1 000-1\ 000 \le x_{i,j} \le 1\ 000−1 000≤xi,j​≤1 000 ,xi,j≠1000x_{i,j} \ne 1000xi,j​≠1000 . The number xi,jx_{i,j}xi,j​ describes the jjj ‘th square of the iii ‘th line. The ground level in this square is ∣xi,j∣|x_{i,j}|∣xi,j​∣ above sea level. If xi,j>0x_{i,j} > 0xi,j​>0 , then the square is part of Byteburg, otherwise it is outside the city. Notice, that the area of Byteburg need not be connected. In fact the city may have several separate parts.

输出格式:

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

样例说明:
这里写图片描述

题意解析:
若在I放置一个抽水机,且J与I之间存在一条路径使得max(H)<=H[j],那么J的水可以被抽干。

算法:并查集

  1. 先将所有点按高度排序。
  2. 枚举每个点,并将它 相邻的点且高度<=这个点的高度 的点与它合并。假设:这个点是a[i], 有一个满足 相邻的点且高度<=这个点的高度 这一条件的点a[j],很明显a[i]的水可以流向a[j], 所以如果a[j]的水已经被抽水机抽完了,那么a[i]的水也会被抽完。
  3. 判断该点是否为城市。如果不为城市,则不需要抽水机。如果为城市且该联通块内没有抽水机,则在该城市放一个抽水机。(注意:这里必须先将同一高度的点都合并了才能判断)

    为什么必须先将同一高度的点都合并了才能判断呢?

    例如数据:
    1 4
    3 3 2 1

    很明显答案是1
    我们来模拟一下,排完序后,数据可能会变为
    1 2 3 3(第3个 ‘3’为 原来序列的第1个)
    那么边做时边判断是否有抽水机
    到第3个3时 联通块为: 1-2 3 就要用两个抽水机了

完整代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int a[N][N];
struct node
{
    int x, y, h;
    bool operator <(const node &z)const
    {
        return h<z.h;
    }
}p[N*N];
int pl;
int fa[N*N], num[N][N], s[N*N];
int find(int x)
{
    if(fa[x] == x) return x;
    return fa[x] = find(fa[x]);
}
int mov[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
void hb(int x, int y)
{
    int X = find(x), Y = find(y);
    s[Y] |= s[X];
    fa[X] = Y;
    /*这里要注意了,不能是fa[Y] = X。 
    如果是fa[Y] = X, 那么前面应改成s[X] |= s[Y]。
    假如, Y集合中有抽水机, X集合中没有。
    按
        s[Y] |= s[X];
        fa[Y] = X;
    那么合并后 s[Y] = 1, s[X] = 0。
    如果是
    则find(Y) = X
    s[X] = 0, 所以集合中没有抽水机。
    然而,这个集合是有抽水机的。
    */
    return ;
}
int main()
{
    int n, m, ans = 0;
    scanf("%d%d", &n, &m);
    memset(a, 127, sizeof(a));
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            scanf("%d", &a[i][j]);
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
        {
            num[i][j] = pl;
            p[++pl] = (node){i, j, abs(a[i][j])};
        }
    sort(p+1, p+1+pl);
    for(int i = 1; i <= pl; i++)
        fa[i] = i;
    for(int i = 1; i <= pl; i++)
    {
        int X = p[i].x, Y = p[i].y;
        for(int j = 0; j < 4; j++)
        {
            int x = X + mov[j][0], y = Y + mov[j][1];
            if(abs(a[x][y]) <= p[i].h)
                hb(num[x][y], num[X][Y]);
        }
        if(p[i].h != p[i+1].h)
            for(int j = i; p[j].h == p[i].h; j--)
                if(a[p[j].x][p[j].y]>0)
                {
                    int x = find(num[p[j].x][p[j].y]);
                    if(!s[x])
                        s[x] = 1, ans++;
                }
    }
    printf("%d\n", ans);
    return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值