bzoj3144 [Hnoi2013]切糕

Description

P

Input

第一行是三个正整数P,Q,R,表示切糕的长P、 宽Q、高R。
第二行有一个非负整数D,表示光滑性要求。接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R)。
100%的数据满足P,Q,R≤40,0≤D≤R,且给出的所有的不和谐值不超过1000。

Output

仅包含一个整数,表示在合法基础上最小的总不和谐值。

Sample Input

样例1:
2 2 2
1
6 1
6 1
2 6
2 6

样例2:
2 2 2
0
5 1
5 1
2 5
2 5

Sample Output

样例1:
6

样例2:
12

Hint

第一组样例中最佳切面的f为f(1,1)=f(2,1)=2,f(1,2)=f(2,2)=1。

第二组样例中最佳切面的f为f(1,1)=f(2,1)=f(1,2)=f(2,2)=1。

正解:最小割。

这题连边很难啊,我只知道一个纵轴上的点要连起来,然后就没点思路了。。

考虑如何将当前轴相邻的轴连边。如果当前点高度为k,那么就把当前点和相邻的高度为k-d的点相连。这样,我们就能在当前点与相邻点的[k-d,k+d]范围取一个最小值了。因为画图以后可以发现,这个范围形成了一个环,一个环的最大流肯定是环上的最小容量。这样,我们求出最大流以后,根据最小割最大流定理,我们求的也就是使得这个图不连通的最小割了。

 

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <complex>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <cmath>
10 #include <queue>
11 #include <stack>
12 #include <map>
13 #include <set>
14 #define inf (1<<30)
15 #define il inline
16 #define RG register
17 #define ll long long
18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
19 
20 using namespace std;
21 
22 struct edge{ int nt,to,flow,cap; }g[5000010];
23 
24 int head[100010],que[100010],d[100010],v[50][50][50],c[50][50][50],p,q,r,D,S,T,cnt,num=1;
25 
26 il int gi(){
27     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
28     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
29 }
30 
31 il void insert(RG int from,RG int to,RG int cap){ g[++num]=(edge){head[from],to,0,cap},head[from]=num; return; }
32 
33 il int bfs(RG int S,RG int T){
34     memset(d,0,sizeof(d)); RG int h=0,t=1; que[t]=S,d[S]=1;
35     while (h<t){
36     RG int x=que[++h];
37     for (RG int i=head[x];i;i=g[i].nt){
38         RG int v=g[i].to;
39         if (!d[v] && g[i].cap>g[i].flow){
40         que[++t]=v,d[v]=d[x]+1;
41         if (v==T) return 1;
42         }
43     }
44     }
45     return 0;
46 }
47 
48 il int dfs(RG int x,RG int T,RG int a){
49     if (x==T || !a) return a; RG int f,flow=0;
50     for (RG int i=head[x];i;i=g[i].nt){
51     RG int v=g[i].to;
52     if (d[v]==d[x]+1 && g[i].cap>g[i].flow){
53         f=dfs(v,T,min(a,g[i].cap-g[i].flow));
54         g[i].flow+=f,g[i^1].flow-=f;
55         flow+=f,a-=f; if (!a) return flow;
56     }
57     }
58     if (!flow) d[x]=-1; return flow;
59 }
60 
61 il int maxflow(RG int S,RG int T){ RG int flow=0; while (bfs(S,T)) flow+=dfs(S,T,inf); return flow; }
62 
63 il void work(){
64     p=gi(),q=gi(),r=gi(),D=gi(),S=++cnt,T=++cnt;
65     for (RG int i=1;i<=p;++i)
66     for (RG int j=1;j<=q;++j)
67         c[i][j][0]=++cnt,insert(S,c[i][j][0],inf),insert(c[i][j][0],S,0);
68     for (RG int k=1;k<=r;++k)
69     for (RG int i=1;i<=p;++i)
70         for (RG int j=1;j<=q;++j) v[i][j][k]=gi(),c[i][j][k]=++cnt;
71     for (RG int i=1;i<=p;++i)
72     for (RG int j=1;j<=q;++j){
73         for (RG int k=1;k<=r;++k){
74         insert(c[i][j][k-1],c[i][j][k],v[i][j][k]),insert(c[i][j][k],c[i][j][k-1],0);
75         if (i>1 && k>D) insert(c[i][j][k],c[i-1][j][k-D],inf),insert(c[i-1][j][k-D],c[i][j][k],0);
76         if (i<p && k>D) insert(c[i][j][k],c[i+1][j][k-D],inf),insert(c[i+1][j][k-D],c[i][j][k],0);
77         if (j>1 && k>D) insert(c[i][j][k],c[i][j-1][k-D],inf),insert(c[i][j-1][k-D],c[i][j][k],0);
78         if (j<q && k>D) insert(c[i][j][k],c[i][j+1][k-D],inf),insert(c[i][j+1][k-D],c[i][j][k],0);
79         }
80         insert(c[i][j][r],T,inf),insert(T,c[i][j][r],0);
81     }
82     printf("%d\n",maxflow(S,T)); return;
83 }
84 
85 int main(){
86     File("cake");
87     work();
88     return 0;
89 }

 

posted @ 2017-02-24 21:33  wfj_2048  阅读(213)  评论(0编辑  收藏  举报