## [bzoj3144][网络流-最小割]切糕

Description

Input

100%的数据满足P,Q,R≤40，0≤D≤R，且给出的所有的不和谐值不超过1000。

Output

Sample Input

2 2 2

1

6 1

6 1

2 6

2 6

Sample Output

6

HINT

YY了一个一定满流的最小割= =

st向底面每个点连边，流量INF

``````#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int dx[4]={0,-1,0,1};
const int dy[4]={-1,0,1,0};
struct node
{
int x,y,c,next,other;
}a[810000];int len,last[210000];
void ins(int x,int y,int c)
{
int k1,k2;
k1=++len;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=last[x];last[x]=len;
k2=++len;
a[len].x=y;a[len].y=x;a[len].c=0;
a[len].next=last[y];last[y]=len;
a[k1].other=k2;
a[k2].other=k1;
}
int list[2110000],st,ed;
bool bt_h()
{
memset(h,0,sizeof(h));h[st]=1;
{
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(a[k].c>0 && h[y]==0)
{
h[y]=h[x]+1;
list[tail++]=y;
}
}
}
if(h[ed]==0)return false;
return true;
}
int findflow(int x,int f)
{
if(x==ed)return f;
int s=0,t;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(h[y]==h[x]+1 && a[k].c>0 && s<f)
{
s+=(t=findflow(y,min(a[k].c,f-s)));
a[k].c-=t;a[a[k].other].c+=t;
}
}
if(s==0)h[x]=0;
return s;
}
int P,Q,R,D;
bool chk(int x,int y){if(x>=1 && x<=P && y>=1 && y<=Q)return true;return false;}
int val[45][45][45];
int pt(int x,int y,int z){return (z-1)*P*Q+(x-1)*Q+y;}
int main()
{
//  freopen("d.in","r",stdin);
//  freopen("d.out","w",stdout);
scanf("%d%d%d",&P,&Q,&R);
scanf("%d",&D);
st=P*Q*(R+1)+1;ed=P*Q*(R+1)+2;
for(int i=1;i<=R;i++)
for(int j=1;j<=P;j++)
for(int k=1;k<=Q;k++)scanf("%d",&val[j][k][i]),ins(pt(j,k,i),pt(j,k,i+1),val[j][k][i]);
for(int i=D+1;i<=R;i++)
for(int j=1;j<=P;j++)
for(int k=1;k<=Q;k++)
for(int l=0;l<=3;l++)
if(chk(j+dx[l],k+dy[l]))
ins(pt(j,k,i),pt(j+dx[l],k+dy[l],i-D),999999999);
for(int i=1;i<=P;i++)for(int j=1;j<=Q;j++)ins(st,pt(i,j,1),999999999),ins(pt(i,j,R+1),ed,999999999);
int ans=0;
while(bt_h())ans+=findflow(st,99999999);
printf("%d\n",ans);
return 0;
}``````