BZOJ 3144 [Hnoi2013]切糕 ——网络流

【题目分析】

    网络流好题!

    从割的方面来考虑问题往往会得到简化。

    当割掉i,j,k时,必定附近的要割在k-D到k+D上。

    所以只需要建两条inf的边来强制,如果割不掉强制范围内的时候,原来的边一定会换到另外一个位置。

    妙啊!

    http://blog.csdn.net/thy_asdf/article/details/50428973

    ↑解释的图画的不错。

【代码】

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>

//#include <map>
#include <set>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 500005
#define me 300005 
#define inf 0x3f3f3f3f
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)

void Finout()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    #endif
}

int Getint()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}

int h[me],to[me<<1],ne[me<<1],fl[me<<1],en=0,S=0,T=me-1;
int mov[4][2]={{1,0},{0,1},{-1,0},{0,-1}};

void add(int a,int b,int c)
{
    to[en]=b; ne[en]=h[a]; fl[en]=c; h[a]=en++;
    to[en]=a; ne[en]=h[b]; fl[en]=0; h[b]=en++;
}

int map[me];

bool tell()
{
	queue <int> q;
    memset(map,-1,sizeof map);
    map[S]=0;
    q.push(S);
    while (!q.empty())
    {
        int x=q.front(); q.pop();
        for (int i=h[x];i>=0;i=ne[i])
        {
            if (map[to[i]]==-1&&fl[i]>0)
            {
                map[to[i]]=map[x]+1;
                q.push(to[i]);
            }
        }
    }
    if (map[T]!=-1) return true;
    return false;
}

int zeng(int k,int r)
{
    if (k==T) return r;
    int ret=0;
    for (int i=h[k];i>=0&&ret<r;i=ne[i])
        if (map[to[i]]==map[k]+1&&fl[i]>0)
        {
            int tmp=zeng(to[i],min(fl[i],r-ret));
            ret+=tmp; fl[i]-=tmp; fl[i^1]+=tmp;
        }
    if (!ret) map[k]=-1;
    return ret;
}

int r,p,q,cnt=0,D;
int a[41][41][41],hash[41][41][41];

int main()
{
	memset(h,-1,sizeof h);
    Finout();
    p=Getint(); q=Getint(); r=Getint(); D=Getint();
    F(i,1,r) F(j,1,p) F(k,1,q)
    	a[j][k][i]=Getint();
    F(i,1,p) F(j,1,q) F(k,1,r) hash[i][j][k]=++cnt;
    F(i,1,p) F(j,1,q)
	{
		F(k,1,r)
	    {
	    	add(hash[i][j][k-1],hash[i][j][k],a[i][j][k]);
	    	if (k>D)
	    	{
	    		int nx,ny;
	    		F(l,0,3)
	    		{
	    			nx=i+mov[l][0];
	    			ny=j+mov[l][1];
	    			if (nx<1||nx>p||ny<1||ny>q) continue;
	    			add(hash[i][j][k],hash[nx][ny][k-D],inf);
				}
			}
		}
		add(hash[i][j][r],T,inf);
	}
	int ans=0,tmp;
	while (tell()) while (tmp=zeng(S,inf)) ans+=tmp;
	printf("%d\n",ans);
	return 0;
}

  

posted @ 2017-01-03 23:34  SfailSth  阅读(103)  评论(0编辑  收藏  举报