[bzoj3144]切糕

对于P*Q的矩形中每一个点挂一条长度为R的链,流量分别是下一个点的点权(链尾是inf),然后对于每一个点连向四周的后D个点连一条inf的边。

考虑最小割,当割掉某一条链的一条边,就表示选择该边,那么如果割掉的两条边相差大于D,那么一定可以顺着在前面的那个点走到另一条路上在走到汇点,不是满足条件的割。

另外,一个位置上如果割了两次,总有一次没有意义(可以多次沿着向后D个点的边移动),因此不存在此类情况

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100005
 4 #define id ((i-1)*n+j-1)*m+k
 5 #define inf 0x3f3f3f3f
 6 struct ji{
 7     int nex,to,len;
 8 }edge[N*8];
 9 queue<int>q;
10 int E,n,m,t,l,p,head[N],work[N],d[N];
11 void add(int x,int y,int z){
12     edge[E].nex=head[x];
13     edge[E].to=y;
14     edge[E].len=z;
15     head[x]=E++;
16     if (E&1)add(y,x,0);
17 }
18 bool bfs(){
19     memset(d,-1,sizeof(d));
20     q.push(0);
21     d[0]=0;
22     while (!q.empty()){
23         int k=q.front();
24         q.pop();
25         for(int i=head[k];i!=-1;i=edge[i].nex)
26             if ((edge[i].len)&&(d[edge[i].to]<0)){
27                 d[edge[i].to]=d[k]+1;
28                 q.push(edge[i].to);
29             }
30     }
31     return d[n]>=0;
32 }
33 int dfs(int k,int s){
34     if (k==n)return s;
35     int p;
36     for(int &i=work[k];i!=-1;i=edge[i].nex)
37         if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){
38             p=dfs(edge[i].to,min(s,edge[i].len));
39             if (p){
40                 edge[i].len-=p;
41                 edge[i^1].len+=p;
42                 return p;
43             }
44         }
45     return 0;
46 }
47 int dinic(){
48     int k,ans=0;
49     while (bfs()){
50         memcpy(work,head,sizeof(head));
51         while (k=dfs(0,inf))ans+=k;
52     }
53     return ans;
54 }
55 int main(){
56     scanf("%d%d%d%d",&n,&m,&t,&l);
57     memset(head,-1,sizeof(head));
58     for(int i=1;i<=t;i++)
59         for(int j=1;j<=n;j++)
60             for(int k=1;k<=m;k++){
61                 scanf("%d",&p);
62                 if (i==1)add(0,id,p);
63                 else add(id-n*m,id,p);
64                 if (i==t)add(id,n*m*t+1,inf);
65                 if (i>l){
66                     if (k>1)add(id,id-l*n*m-1,inf);
67                     if (k<m)add(id,id-l*n*m+1,inf);
68                     if (j>1)add(id,id-l*n*m-m,inf);
69                     if (j<n)add(id,id-l*n*m+m,inf);
70                 }
71             }
72     n=n*m*t+1;
73     printf("%d",dinic());
74 }
View Code

 

posted @ 2019-07-28 10:38  PYWBKTDA  阅读(91)  评论(0编辑  收藏  举报