【bzoj3144】[Hnoi2013]切糕 最小割

[Hnoi2013]切糕

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 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

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 }

 

posted @ 2018-01-12 19:23  Kaiser-  阅读(182)  评论(0编辑  收藏  举报