bzoj 3144 切糕 最小割 解题报告

来源:互联网 发布:淘宝联盟用红包有返利 编辑:程序博客网 时间:2024/05/22 06:49

题目描述

这里写图片描述

思路

经典最小割模型。
题面简化为,一个矩阵,每个格子分配一个数,不同的数字,代价不同,要求相邻格子数字差小等于d,求最小代价
每个格子拆出40个点。
连同S与T用40种代价串起来
即 p(x,y,z)->p(x,y,z+1)边权f(x,y,z+1),然后 p(x,y,z)->p(x’,y’,z-d)边权inf (x,y)与(x’,y’)相邻。

代码

其实这个代码我还不会灵活的运用。。姑且码出来吧也不知道对不对好不好反正就那样

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cmath>#include<vector>#include<queue>using namespace std;const int inf=100000000;const int N=100000+5;int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};int P,Q,r,d,T,cnt=1,cake[45][45][45];int cur[N],last[N],h[N],q[N];struct edge{    int to,next,v;}e[N*10];int p(int x,int y,int z){    if (z==0) return 0;    return (z-1)*P*Q+(x-1)*Q+y;}void insert(int u,int v,int w){    e[++cnt].to=v;e[++cnt].to=u;    e[cnt].next=last[u];e[cnt].next=last[v];    last[u]=cnt;last[v]=cnt;    e[cnt].v=w;e[cnt].v=0;}void build(){    for (int i=1;i<=P;i++)    for (int j=1;j<=Q;j++)    {        for (int k=1;k<=r;k++)        {            insert(p(i,j,k-1),p(i,j,k),cake[i][j][k]);            if (k>d) for (int lia=0;lia<4;lia++)            {                int x=i+xx[lia],y=j+yy[lia];                if (x<1||y<1||x>P||y>Q) continue;                insert(p(i,j,k),p(x,y,k-d),inf);            }        }    insert(p(i,j,r),T,inf);    }}bool bfs(){    int head=0,tail=1;    memset(h,-1,sizeof(h));    q[0]=0;h[0]=0;    while(head!=tail)    {        int now=q[head];head++;        for (int i=last[now];i;i=e[i].next)        if (h[e[i].to]==-1&&e[i].v)        {            h[e[i].to]=h[now]+1;            q[tail++]=e[i].to;        }    }    return h[T]!=-1;}int dfs(int x,int f){    if (x==T) return f;    int w,used=0;    for (int i=cur[x];i;i=e[i].next)    if(h[x]+1==h[e[i].to])    {        w=dfs(e[i].to,min(f-used,e[i].v));        used+=w;e[i].v-=w;e[i^1].v+=w;        if (e[i].v) cur[x]=i;        if (used==f) return f;    }    if (!used) h[x]=-1;    return used;}int dinic(){    int tmp=0;    while(bfs())    {        for (int i=0;i<=T;i++)        cur[i]=last[i];        tmp+=dfs(0,inf);    }    return tmp;}int main(){    scanf("%d%d%d%d",&P,&Q,&r,&d);    T=P*Q*r+1;    for (int i=1;i<=r;i++)    for (int j=1;j<=P;j++)    for (int k=1;k<=Q;k++)    scanf("%d",&cake[i][j][k]);//  cake[j][k][i]=read();    build();    printf("%d\n",dinic());    return 0;}
原创粉丝点击