[BZOJ3144][HNOI2013]切糕 最小割

来源:互联网 发布:java heap space -xss 编辑:程序博客网 时间:2024/03/29 03:29

核心思想:在最小割中用容量为无穷大的边来表示限制。
这题相当于一个pq的矩阵,每个矩阵添一个[0,r]的数,且相邻数之差不超过d,同时最小化v(i,j,k)
先把一个格子的取值串起来,就是(i,j,k)(i,j,k+1)连一条容量为v(i,j,k+1)的边;
特别地,S(i,j,1)连一条容量为(i,j,1)的边,(i,j,r)向T连一条容量为无穷大的边;
那么这些边中必须割一条,表示填的数是什么。
然后考虑差不超过d的限制,就是(i,j,k)(i1,j,kd)(i+1,j,kd)(i,j1,kd)(i,j+1,kd)连一条容量为无穷大的边。
这样就保证不能同时割(i,j,k)(kd);因为每串最多割一条边。
代码:

#include<iostream>#include<cstdio>#include<cstring> #define G(x,y,z) (((x-1)*m+y-1)*r+z-1)using namespace std;int n,m,r,d,v[45][45][45],S,T,dl[64010],ne[64010];bool vis[64010];struct edge{    int t,c,f;    edge *next,*rev;}*con[64010];void ins(int x,int y,int c){    edge *p=new edge;p->t=y;p->c=c;p->f=0;p->next=con[x];con[x]=p;    p=new edge;p->t=x;p->c=0;p->f=0;p->next=con[y];con[y]=p;    con[x]->rev=con[y];con[y]->rev=con[x];}bool bfs(){    bool re=0;    memset(ne,0,sizeof(ne));    ne[S]=1;dl[1]=S;    for(int head=1,tail=1;head<=tail;head++)    {        int v=dl[head];        if(v==T) re=1;        for(edge *p=con[v];p;p=p->next)            if(p->c>p->f&&ne[p->t]==0)                ne[p->t]=ne[v]+1,dl[++tail]=p->t;    }    return re;}int dinic(int v,int flow){    if(v==T) return flow;    if(vis[v]) return 0;    int re=0;    for(edge *p=con[v];p;p=p->next)        if(p->c>p->f&&ne[p->t]==ne[v]+1)        {            int tmp=dinic(p->t,min(flow,p->c-p->f));            re+=tmp;p->f+=tmp;            flow-=tmp;p->rev->f-=tmp;            if(flow==0) break;        }    if(re==0) vis[v]=1;    return re;  }int main(){    scanf("%d%d%d%d",&n,&m,&r,&d);    for(int i=1;i<=r;i++)        for(int j=1;j<=n;j++)            for(int k=1;k<=m;k++)                scanf("%d",&v[j][k][i]);    S=n*m*r;T=n*m*r+1;              for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)        {            for(int k=1;k<=r;k++)            {                ins(k==1?S:G(i,j,k-1),G(i,j,k),v[i][j][k]);                if(k-d>0)                {                    if(i>1) ins(G(i,j,k),G(i-1,j,k-d),0x3f3f3f3f);                    if(i<n) ins(G(i,j,k),G(i+1,j,k-d),0x3f3f3f3f);                    if(j>1) ins(G(i,j,k),G(i,j-1,k-d),0x3f3f3f3f);                    if(j<m) ins(G(i,j,k),G(i,j+1,k-d),0x3f3f3f3f);                }            }            ins(G(i,j,r),T,0x3f3f3f3f);        }    int ans=0;    while(bfs())    {        memset(vis,0,sizeof(vis));        ans+=dinic(S,0x3f3f3f3f);    }    printf("%d",ans);    return 0;}