BZOJ5101 : [POI2018]Powód

求出Kruskal重构树,那么重构树上每个点的取值范围是定的。

考虑树形DP,则对于一个点,要么所有点水位相同,要么还未发生合并。

故$dp[x]=up[x]-down[x]+1+dp[l[x]]\times dp[r[x]]$。

时间复杂度$O(nm\log(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;
}

  

posted @ 2017-12-02 02:16 Claris 阅读(...) 评论(...) 编辑 收藏