bzoj3144: [Hnoi2013]切糕 DINIC最小割

来源:互联网 发布:薛之谦的淘宝店女装 编辑:程序博客网 时间:2024/04/16 13:43

很容易想到把每对相邻两层的对应点连容量为C(不和谐值)的边。

对于条件高度差不超过d,对于最小割的模型,我们可以想到所有限制流量的边可以抽象在同一层中。

若当前边选作了最小割的一个边,那么这个点往下的点(对于第i层往后的点)都是摆设,而最小割的这一层不能断,所以向与当前点层数差为d的点连容量为INF的边。

#include<iostream>#include<cmath>#include<cstdio>#include<cstdlib>#include<string>#include<cstring>#include<algorithm>#include<vector>#define INF 0x3fffffffusing namespace std;#define maxn 444444#define INF 0x3fffffffstruct node{    int next,c,v;}e[maxn];int en,ed,st,q[maxn],n,m,h,d,num;int dis[maxn],first[maxn],cur[maxn];int lab[50][50][50];int dx[]={0,1,0,0,-1};int dy[]={0,0,1,-1,0};bool bfs(){    memset(dis,-1,sizeof(dis));    dis[st]=0;    int tail,head;    tail=head=1;    tail++;    q[tail]=st;    int v,u;    while(head<tail)    {        head++;        u=q[head];        for(int i=first[u];i!=-1;i=e[i].next)        {            v=e[i].v;            if(dis[v]!=-1) continue;            if(e[i].c==0) continue;            dis[v]=dis[u]+1;            tail++;            q[tail]=v;            if(v==ed) return true;        }    }    return false;}int dfs(int x,int mx){    if(x==ed||mx==0) return mx;    int f,flow=0,v,ret=0;    for(int& i=cur[x];i!=-1;i=e[i].next)    {        v=e[i].v;        if(dis[x]+1!=dis[v]) continue;        if((f=dfs(v,min(mx,e[i].c))))        {            e[i].c-=f;            e[i^1].c+=f;            flow+=f;            ret+=f;            mx-=f;            if(!mx) break;        }    }    if(ret==0) dis[x]=-1;    return flow;}int dinic(){    int tmp=0,maxflow=0;    while(bfs())    {        for(int i=1;i<=ed;i++) cur[i]=first[i];        while(tmp=dfs(st,INF)) maxflow+=tmp;    }    return maxflow;}void add(int a,int b,int c){    e[en].v=b;    e[en].next=first[a];    e[en].c=c;    first[a]=en;    en++;    e[en].v=a;    e[en].next=first[b];    e[en].c=0;    first[b]=en;    en++;}void init(){    memset(first,-1,sizeof(first));    en=0;    for(int i=1;i<=h+1;i++)    {        for(int j=1;j<=n;j++)        {            for(int k=1;k<=m;k++)            {                num++;                lab[i][j][k]=num;            }        }    }    st=num+1;    ed=st+1;    for(int i=1;i<=n;i++)    {        for(int j=1;j<=m;j++)        {            add(st,lab[1][i][j],INF);            add(lab[1+h][i][j],ed,INF);        }    }    int a,b,c;    for(int k=1;k<=h;k++)    {        for(int i=1;i<=n;i++)        {            for(int j=1;j<=m;j++)            {                scanf("%d",&c);                add(lab[k][i][j],lab[k+1][i][j],c);            }        }    }    int xx,yy;    for(int k=1;k<=h;k++)    {        for(int i=1;i<=n;i++)        {            for(int j=1;j<=m;j++)            {                if(k+d>h+1) continue;                for(int t=1;t<=4;t++)                {                    xx=i+dx[t];                    yy=j+dy[t];                    if(lab[k+d][xx][yy])                    {                        add(lab[k+d][xx][yy],lab[k][i][j],INF);                    }                }            }        }    }}int main(){    scanf("%d%d%d%d",&n,&m,&h,&d);    init();        printf("%d\n",dinic());    return 0;}


0 0
原创粉丝点击