【bzoj3144】[Hnoi2013]切糕 最小割
[Hnoi2013]切糕
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2228 Solved: 1220
[Submit][Status][Discuss]
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
2 2 2
1
6 1
6 1
2 6
2 6
1
6 1
6 1
2 6
2 6
Sample Output
6
HINT
最佳切面的f为f(1,1)=f(2,1)=2,f(1,2)=f(2,2)=1
Source
题解:
题意表示看不懂了,语文水平差,没办法。
切割就是每条竖线上选择一个点来断开,
如果没有这个限制是什么,就是直接一层中的点向下一层对应的点连边
那么限制的话就是当前的点割了不能割
那么就是也可以转换为,割了这条边,与其相距d的边割了无效
发现一个点向上向下都制约D和每个点都只向下制约是等价的。
所以从该点向下d连一条无穷的边,不能割
当时看这个人才会的
1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 7 #define rad 100000000 8 #define inf 1000000000 9 #define ll long long 10 #define eps 1e-10 11 #define pa pair<ll,int> 12 using namespace std; 13 ll read() 14 { 15 ll x=0,f=1;char ch=getchar(); 16 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 17 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 21 int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0}; 22 int P,Q,r,d,T,cnt=1; 23 int f[45][45][45]; 24 int cur[100005],last[100005],h[100005],q[100005]; 25 26 struct edge{ 27 int to,next,v; 28 }e[1000005]; 29 int p(int x,int y,int z) 30 { 31 if(z==0)return 0; 32 return (z-1)*P*Q+(x-1)*Q+y; 33 } 34 void insert(int u,int v,int w) 35 { 36 e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w; 37 e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;e[cnt].v=0; 38 } 39 void build() 40 { 41 for(int i=1;i<=P;i++) 42 for(int j=1;j<=Q;j++) 43 { 44 for(int k=1;k<=r;k++) 45 { 46 insert(p(i,j,k-1),p(i,j,k),f[i][j][k]); 47 if(k>d) 48 for(int dir=0;dir<4;dir++) 49 { 50 int nx=i+xx[dir],ny=j+yy[dir]; 51 if(nx<1||ny<1||nx>P||ny>Q)continue; 52 insert(p(i,j,k),p(nx,ny,k-d),inf); 53 } 54 } 55 insert(p(i,j,r),T,inf); 56 } 57 } 58 bool bfs() 59 { 60 int head=0,tail=1; 61 memset(h,-1,sizeof(h)); 62 q[0]=0;h[0]=0; 63 while(head!=tail) 64 { 65 int now=q[head];head++; 66 for(int i=last[now];i;i=e[i].next) 67 if(h[e[i].to]==-1&&e[i].v) 68 { 69 h[e[i].to]=h[now]+1; 70 q[tail++]=e[i].to; 71 } 72 } 73 return h[T]!=-1; 74 } 75 int dfs(int x,int f) 76 { 77 if(x==T)return f; 78 int w,used=0; 79 for(int i=cur[x];i;i=e[i].next) 80 if(h[x]+1==h[e[i].to]) 81 { 82 w=dfs(e[i].to,min(f-used,e[i].v)); 83 used+=w;e[i].v-=w;e[i^1].v+=w; 84 if(e[i].v)cur[x]=i; 85 if(used==f)return f; 86 } 87 if(!used)h[x]=-1; 88 return used; 89 } 90 int dinic() 91 { 92 int tmp=0; 93 while(bfs()) 94 { 95 for(int i=0;i<=T;i++)cur[i]=last[i]; 96 tmp+=dfs(0,inf); 97 } 98 return tmp; 99 } 100 int main() 101 { 102 P=read();Q=read();r=read();T=P*Q*r+1; 103 d=read(); 104 for(int i=1;i<=r;i++) 105 for(int j=1;j<=P;j++) 106 for(int k=1;k<=Q;k++) 107 f[j][k][i]=read(); 108 build(); 109 printf("%d\n",dinic()); 110 }