洪水 Pow

Description

AKD市处在一个四面环山的谷地里。最近一场大暴雨引发了洪水,AKD市全被水淹没了。Blue Mary,AKD市的市长,召集了他的所有顾问(包括你)参加一个紧急会议。经过细致的商议之后,会议决定,调集若干巨型抽水机,将它们放在某些被水淹的区域,而后抽干洪水。 
你手头有一张AKD市的地图。这张地图是边长为m*n的矩形,被划分为m*n个1*1的小正方形。对于每个小正方形,地图上已经标注了它的海拔高度以及它是否是AKD市的一个组成部分。地图上的所有部分都被水淹没了。并且,由于这张地图描绘的地面周围都被高山所环绕,洪水不可能自动向外排出。显然,我们没有必要抽干那些非AKD市的区域。 
每个巨型抽水机可以被放在任何一个1*1正方形上。这些巨型抽水机将持续地抽水直到这个正方形区域里的水被彻底抽干为止。当然,由连通器原理,所有能向这个格子溢水的格子要么被抽干,要么水位被降低。每个格子能够向相邻的格子溢水,“相邻的”是指(在同一高度水平面上的射影)有公共边。 

Input

第一行是两个数m,n(1<=m,n<=1000). 
以下m行,每行n个数,其绝对值表示相应格子的海拔高度;若该数为正,表示他是AKD市的一个区域;否则就不是。 
请大家注意:所有格子的海拔高度其绝对值不超过1000,且可以为零. 

Output

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

 

Sample 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
 
 

Sample Output

2

Hint


题解:

结论:若在I放置一个抽水机,且J与I之间存在一条路径使得max(H)<=H[j],那么J的水可以被抽干。所以显然我们要在所有“山谷”放抽水机。

将格子按高度从小到大加入,加入I时将其与相邻的格子并入一个集合,若I需要抽水且合并后I属于的集合没有抽水机则在I处放置一个抽水机。

细节:将同一高度的格子合并完后再放置抽水机。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
int n,m,tot,ans,last=1;
int map[1000005],h[1000005],b[1000005],vis[1000005],t[5]={-1,0,1,0,-1},p[1000005],father[1000005];
int gi()
{
    int ans=0,f=1;
    char i=getchar();
    while(i<'0'||i>'9'){if(i=='-')f=-1;i=getchar();}
    while(i>='0'&&i<='9'){ans=ans*10+i-'0';i=getchar();}
    return ans*f;
}
int make(int x,int y)
{
    return (x-1)*m+y;
}
bool cmp(int a,int b)
{
    return h[a]<h[b];
}
int find(int x)
{
    if(father[x]==x)return x;
    else return father[x]=find(father[x]);
}
int main()
{
    int i,j;
    n=gi();m=gi();
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            int x=make(i,j);
            h[x]=gi();
            father[x]=x;
            map[++tot]=x;
            if(h[x]>0)b[x]=1;
            else h[x]=-h[x];
        }
    }
    sort(map+1,map+tot+1,cmp);
    for(i=1;i<=tot;i++)
    {
        int a=map[i],y=(a-1)%m+1,x=(a-1)/m+1;
        for(j=0;j<4;j++)
        {
            int xx=x+t[j],yy=y+t[j+1];
            if(xx>=1&&xx<=n&&yy>=1&&yy<=m)
            {
                int b=make(xx,yy);
                if(vis[b])
                {
                    int fa=find(b);
                    p[a]|=p[fa];
                    father[fa]=find(a);
                }
            }
        }
        vis[a]=1;
        if(h[map[i]]!=h[map[i+1]])
        {
            for(j=last;j<=i;j++)
            {
                if(b[map[j]]&&!p[find(map[j])])
                {
                    ans++;
                    p[find(map[j])]=1;
                }
            }
            last=i+1;
        }
    }
    printf("%d
",ans);
    return 0;
}

转载于:https://www.cnblogs.com/huangdalaofighting/p/7219579.html

原文地址:https://www.cnblogs.com/twodog/p/12139869.html