bzoj3144 [Hnoi2013]切糕
Description
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 }