题解 P5952 【[POI2018]水箱】

· · 题解

题意

给定一个高为H的水箱,水箱被划分为n*m个格子,每个相邻的格子之间都有一堵墙,高度为h_i,每个格子高度都是[0,H]之间的整数,求有多少种可能的水位情况。

分析

代码

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();};
    while(c>='0'&&c<='9')
    {
        x=(x<<3)+(x<<1)+(c^48);
        c=getchar();
    }
    return x*f;
}
#define ll long long
const int N=5e5+5,mod=1e9+7;
struct edge
{
    int x,y,v;
}e[N<<1];
int cnt;
bool mycmp(edge x,edge y)
{
    return x.v<y.v;
}
int f[N];
int get(int x)
{
    if(x^f[x]) f[x]=get(f[x]);
    return f[x];
}
int n,m,H,ans[N],h[N];
int ya(int x,int y)
{
    return (x-1)*m+y;
}
int main()
{
    n=read(),m=read(),H=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<m;j++)
        {
            int x=ya(i,j),y=ya(i,j+1),v=read();
            e[++cnt]={x,y,v}; 
        }
    for(int i=1;i<n;i++)
        for(int j=1;j<=m;j++)
        {
            int x=ya(i,j),y=ya(i+1,j),v=read();
            e[++cnt]={x,y,v};
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            int x=ya(i,j);
            f[x]=x;
            ans[x]=1;
        }
    sort(e+1,e+cnt+1,mycmp);
    for(int i=1;i<=cnt;i++)
    {
        int x=get(e[i].x),y=get(e[i].y),v=e[i].v;
        if(x^y)
        {
            f[y]=x;
            ans[x]=1ll*(ans[x]-h[x]+v)*(ans[y]-h[y]+v)%mod;
            h[x]=v;
        }
    }
    int x=get(1);
    printf("%d\n",(ans[x]-h[x]+H)%mod);
    return 0;
}