求出Kruskal重构树,那么重构树上每个点的取值范围是定的。
考虑树形DP,则对于一个点,要么所有点水位相同,要么还未发生合并。
故$dp[x]=up[x]-down[x]+1+dp[l[x]] imes dp[r[x]]$。
时间复杂度$O(nmlog(nm))$。
#include<cstdio> #include<algorithm> const int N=1000010; int n,m,H,ce,i,j,x,y,tot,f[N],son[N][2],l[N],r[N],dp[N]; struct E{int x,y,w;}e[N]; inline bool cmp(const E&a,const E&b){return a.w<b.w;} inline int id(int x,int y){return (x-1)*m+y;} int F(int x){return f[x]==x?x:f[x]=F(f[x]);} inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';} int main(){ read(n),read(m),read(H); for(i=1;i<=n;i++)for(j=1;j<m;j++){ e[++ce].x=id(i,j); e[ce].y=id(i,j+1); read(e[ce].w); } for(i=1;i<n;i++)for(j=1;j<=m;j++){ e[++ce].x=id(i,j); e[ce].y=id(i+1,j); read(e[ce].w); } std::sort(e+1,e+ce+1,cmp); tot=n*m; for(i=1;i<=tot;i++)f[i]=i; for(i=1;i<=ce;i++){ x=F(e[i].x),y=F(e[i].y); if(x!=y){ son[++tot][0]=x; son[tot][1]=y; f[x]=f[y]=f[tot]=tot; r[x]=r[y]=e[i].w; l[tot]=e[i].w+1; } } r[tot]=H; for(i=1;i<=tot;i++)dp[i]=(1LL*dp[son[i][0]]*dp[son[i][1]]+r[i]-l[i]+1)%1000000007; return printf("%d",dp[tot]),0; }