BZOJ3144 切糕
http://www.lydsy.com/JudgeOnline/problem.php?id=3144
思路:如果没有D的限制,那一个竖轴都是一个最小割,每个点向更高的点引一条流量为自己权值的边,那考虑D的情况,就表明在割i高度这条边的时候,不能割它相邻的i-d以下的任何边,因此,我们引一条边从i高度到相邻的i-d高度,流量为inf,这样就能维护D这个条件了
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstring> 5 #include<iostream> 6 #define inf 0x7fffffff 7 int d[5][5]; 8 int sz,id[50][50][50],S,T,nodes,P,Q,R,D; 9 int tot,go[2000005],next[2000005],first[2000005],flow[2000005]; 10 int op[2000005],dis[2000005],cnt[2000005],v[50][50][50]; 11 int read(){ 12 int t=0,f=1;char ch=getchar(); 13 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 14 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 15 return t*f; 16 } 17 void insert(int x,int y,int z){ 18 tot++; 19 go[tot]=y; 20 next[tot]=first[x]; 21 first[x]=tot; 22 flow[tot]=z; 23 } 24 void add(int x,int y,int z){ 25 insert(x,y,z);op[tot]=tot+1; 26 insert(y,x,0);op[tot]=tot-1; 27 } 28 int dfs(int x,int f){ 29 if (x==T) return f; 30 int mn=nodes,sum=0; 31 for (int i=first[x];i;i=next[i]){ 32 int pur=go[i]; 33 if (flow[i]&&dis[pur]+1==dis[x]){ 34 int F=std::min(f-sum,flow[i]); 35 int save=dfs(pur,F); 36 flow[i]-=save; 37 flow[op[i]]+=save; 38 sum+=save; 39 if (sum==f||dis[S]>=nodes) return sum; 40 } 41 if (flow[i]) mn=std::min(mn,dis[pur]); 42 } 43 if (sum==0){ 44 cnt[dis[x]]--; 45 if (cnt[dis[x]]==0) dis[S]=nodes; 46 else { 47 dis[x]=mn+1; 48 cnt[dis[x]]++; 49 } 50 } 51 return sum; 52 } 53 int main(){ 54 P=read();Q=read();R=read(); 55 D=read(); 56 for (int i=1;i<=R+1;i++) 57 for (int j=1;j<=P;j++) 58 for (int k=1;k<=Q;k++) 59 id[i][j][k]=++sz; 60 S=0;T=sz+1;nodes=T+1; 61 for (int i=1;i<=R;i++) 62 for (int j=1;j<=P;j++) 63 for (int k=1;k<=Q;k++) 64 v[i][j][k]=read(); 65 for (int j=1;j<=P;j++) 66 for (int k=1;k<=Q;k++) 67 add(S,id[1][j][k],inf); 68 for (int j=1;j<=P;j++) 69 for (int k=1;k<=Q;k++) 70 add(id[R+1][j][k],T,inf); 71 for (int i=1;i<=R;i++) 72 for (int j=1;j<=P;j++) 73 for (int k=1;k<=Q;k++) 74 add(id[i][j][k],id[i+1][j][k],v[i][j][k]); 75 d[1][1]=d[2][2]=1;d[3][1]=d[4][2]=-1; 76 for (int i=1;i<=R;i++) 77 if (i>D) 78 for (int j=1;j<=P;j++) 79 for (int k=1;k<=Q;k++) 80 for (int l=1;l<=4;l++){ 81 int dx=j+d[l][1],dy=k+d[l][2]; 82 if (dx<1||dx>P||dy<1||dy>Q) continue; 83 add(id[i][j][k],id[i-D][dx][dy],inf); 84 } 85 int ans=0; 86 while (dis[S]<nodes) ans+=dfs(S,inf); 87 printf("%d\n",ans); 88 return 0; 89 }