1. 程式人生 > >【BZOJ 3144】 [Hnoi2013]切糕 真·最小割

【BZOJ 3144】 [Hnoi2013]切糕 真·最小割

getc read str sin bfs 條件 開始 tail pac

一開始一臉懵逼後來發現,他不就是割嗎,我們只要滿足條件就割就行了,於是我們把他連了P*Q*R條邊,然而我們要怎樣限制D呢?我們只要滿足對於任意相鄰的兩條路,只要其有個口大於D就不行就好了因此我們只要把每個點向離他D距離的下面的店連一條Inf連線就可以啦,因此我們就滿足了一定是所有相鄰的路徑上存在不超過距離D的缺口,由於滿足這條性質因此至少存在一層兩兩之間距離不超過D的膜因此最終答案一定是每條路上割一個,因此就讓他跑去把!

#include <cstdio>
#include <cstring>
#define N 50
#define LL 8000000
#define r register
#define
Inf 0x7f7f7f7f using namespace std; inline int read() { r int sum=0; r char ch=getchar(); while(ch<0||ch>9)ch=getchar(); while(ch>=0&&ch<=9) { sum=(sum<<1)+(sum<<3)+ch-0; ch=getchar(); } return sum; } struct VIA { int to,next,f; }c[LL]; int
head[N*N*N],t=1; int q[N*N*N],top,tail,deep[N*N*N],Hash[N][N][N]; int a[N][N][N],S,T; inline void add(int x,int y,int z) { c[++t].to=y; c[t].next=head[x]; head[x]=t; c[t].f=z; } inline bool bfs() { memset(deep,0,sizeof(deep)); deep[S]=1; q[1]=S; top=tail=1; while(top<=tail) { r
int x=q[top++]; if(x==T)return 1; for(int i=head[x];i;i=c[i].next) if(c[i].f&&deep[c[i].to]==0) { deep[c[i].to]=deep[x]+1; q[++tail]=c[i].to; } } return 0; } int dfs(int x,int v) { if(x==T||!v)return v; r int ret=0; for(r int i=head[x];i;i=c[i].next) if(c[i].f&&deep[c[i].to]==deep[x]+1) { r int f=dfs(c[i].to,c[i].f<v?c[i].f:v); v-=f,ret+=f,c[i].f-=f,c[i^1].f+=f; if(!v)break; } if(!ret)deep[x]=-1; return ret; } inline int dinic() { r int ans=0; while(bfs())ans+=dfs(S,Inf); return ans; } int L,W,H,D; int main() { L=read(),W=read(),H=read(),D=read(); S=L*W*H+1,T=S+1; for(r int i=1;i<=H;++i) for(r int j=1;j<=L;++j) for(r int k=1;k<=W;++k) a[j][k][i]=read(),Hash[j][k][i]=(i-1)*L*W+(j-1)*W+k; if(H!=1) { for(r int i=1;i<=L;++i) for(r int j=1;j<=W;++j) { add(S,Hash[i][j][1],a[i][j][1]),add(Hash[i][j][1],S,0); for(r int k=2;k<H;++k) add(Hash[i][j][k-1],Hash[i][j][k],a[i][j][k]),add(Hash[i][j][k],Hash[i][j][k-1],0); add(Hash[i][j][H-1],T,a[i][j][H]),add(T,Hash[i][j][H-1],0); if(H<=1+D)continue; if(i!=1) { add(Hash[i][j][D],S,Inf),add(S,Hash[i][j][D],0); for(r int k=D+1;k<H;++k) add(Hash[i][j][k],Hash[i-1][j][k-D],Inf),add(Hash[i-1][j][k-D],Hash[i][j][k],0); add(T,Hash[i-1][j][H-D],Inf),add(Hash[i-1][j][H-D],T,0); } if(i!=L) { add(Hash[i][j][D],S,Inf),add(S,Hash[i][j][D],0); for(r int k=D+1;k<H;++k) add(Hash[i][j][k],Hash[i+1][j][k-D],Inf),add(Hash[i+1][j][k-D],Hash[i][j][k],0); add(T,Hash[i+1][j][H-D],Inf),add(Hash[i+1][j][H-D],T,0); } if(j!=1) { add(Hash[i][j][D],S,Inf),add(S,Hash[i][j][D],0); for(r int k=D+1;k<H;++k) add(Hash[i][j][k],Hash[i][j-1][k-D],Inf),add(Hash[i][j-1][k-D],Hash[i][j][k],0); add(T,Hash[i][j-1][H-D],Inf),add(Hash[i][j-1][H-D],T,0); } if(j!=W) { add(Hash[i][j][D],S,Inf),add(S,Hash[i][j][D],0); for(r int k=D+1;k<H;++k) add(Hash[i][j][k],Hash[i][j+1][k-D],Inf),add(Hash[i][j+1][k-D],Hash[i][j][k],0); add(T,Hash[i][j+1][H-D],Inf),add(Hash[i][j+1][H-D],T,0); } } } else { for(r int i=1;i<=L;++i) for(r int j=1;j<=W;++j) add(S,T,a[i][j][1]),add(T,S,0); } printf("%d",dinic()); return 0; }

【BZOJ 3144】 [Hnoi2013]切糕 真·最小割