• bzoj3144 [HNOI2013]切糕(最小割)


    bzoj3144 [HNOI2013]切糕(最小割)

    bzoj Luogu

    题面描述见上

    题解时间

    一开始我真就把这玩意所说的切面当成了平面来做的

    事实上只是说相邻的切点高度差都不超过 $ d $

    对于一条 $ z $ 轴方向的线,把原题的点看成边,每个原题的点两端看成两个点就好(就是说一条线上有 $ r+1 $ 个点 $ r $ 条边),底端每一个点有一条由 $ S $ 连向它的不能断开( $ inf $ )的边,顶端每个点同理连向 $ T $

    之后考虑处理相邻两点之间高度差不超过 $ d $

    假设我们已经选了线 $ l_1 $ 上的一个原图点 $ p_1 $,那么与之相邻的一条线 $ l_2 $ 上选择的原图点 $ p_2 $ 纵坐标必须在一个区间内

    从 $ p_1 $ 两端向 $ p_2 $ 可选范围两端连不能断开( $ inf $ )的边就行

    然后直接跑最小割。

    #include<bits/stdc++.h>
    using namespace std;
    template<typename TP>inline void read(TP &tar)
    {
    	TP ret=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
    	tar=ret*f;
    }
    namespace LarjaIX
    {
    const int N=70011,M=1000011,inf=0x3f3f3f3f;
    struct sumireko{int to,ne,w;}e[M<<1];int he[N],ecnt=1;
    void addline(int f,int t,int w)
    {
    	e[++ecnt].to=t,e[ecnt].w=w;
    	e[ecnt].ne=he[f],he[f]=ecnt;
    	e[++ecnt].to=f,e[ecnt].w=0;
    	e[ecnt].ne=he[t],he[t]=ecnt;
    }
    int head[N],dep[N];bool ins[N];
    queue<int> qu;
    bool bfs(int sp,int ep)
    {
    	memcpy(head,he,sizeof(head));
    	memset(dep,0x3f,sizeof(dep));
    	dep[sp]=1,ins[sp]=1,qu.push(sp);
    	while(!qu.empty())
    	{
    		int x=qu.front();qu.pop();ins[x]=0;
    		for(int ei=he[x],t=e[ei].to;ei;ei=e[ei].ne,t=e[ei].to)
    		if(e[ei].w&&dep[t]>dep[x]+1)
    		{
    			dep[t]=dep[x]+1;
    			if(!ins[t]) qu.push(t),ins[t]=1;
    		}
    	}
    	return dep[ep]!=inf;
    }
    int dfs(int x,int lim,int ep)
    {
    	if(x==ep||!lim) return lim;
    	int ret=0,tmp=0;
    	for(int ei=head[x],t=e[ei].to;ei;ei=e[ei].ne,t=e[ei].to)
    	{
    		head[x]=ei;
    		if(dep[t]==dep[x]+1) if(tmp=dfs(t,min(lim,e[ei].w),ep))
    		{
    			lim-=tmp,ret+=tmp;
    			e[ei].w-=tmp,e[ei^1].w+=tmp;
    		}
    	}
    	return ret;
    }
    int dinic(int sp,int ep)
    {
    	int ret=0;
    	while(bfs(sp,ep))
    		ret+=dfs(sp,inf,ep);
    	return ret;
    }
    int p,q,r,d,a[44][44][44],id[44][44][44],ic,S,E;
    int maid()
    {
    	read(p),read(q),read(r),read(d);
    	for(int z=1;z<=r;z++)for(int x=1;x<=p;x++)for(int y=1;y<=q;y++) read(a[x][y][z]);
    	r++;
    	for(int x=1;x<=p;x++)for(int y=1;y<=q;y++)for(int z=1;z<=r;z++) id[x][y][z]=++ic;S=++ic,E=++ic;
    	for(int x=1;x<=p;x++)for(int y=1;y<=q;y++)
    	{
    		addline(S,id[x][y][1],inf),addline(id[x][y][r],E,inf);
    		for(int z=1;z<r;z++)
    		{
    			addline(id[x][y][z],id[x][y][z+1],a[x][y][z]);
    			if(x+1<=p) addline(id[x][y][z],id[x+1][y][max(1,z-d)],inf),addline(id[x+1][y][min(r,z+1+d)],id[x][y][z+1],inf);
    			if(x-1) addline(id[x][y][z],id[x-1][y][max(1,z-d)],inf),addline(id[x-1][y][min(r,z+1+d)],id[x][y][z+1],inf);
    			if(y+1<=q) addline(id[x][y][z],id[x][y+1][max(1,z-d)],inf),addline(id[x][y+1][min(r,z+1+d)],id[x][y][z+1],inf);
    			if(y-1) addline(id[x][y][z],id[x][y-1][max(1,z-d)],inf),addline(id[x][y-1][min(r,z+1+d)],id[x][y][z+1],inf);
    		}
    	}
    	printf("%d
    ",dinic(S,E));
    	return 0;
    }
    }
    int main(){return LarjaIX::maid();}
    
  • 相关阅读:
    Java SE 5.0(JDK 1.5)新特性
    第22章—开启HTTPS
    第21章—websocket
    IE8Get请求中文不兼容:encodeURI的使用
    JavaScript自定义函数
    disable的错误使用
    20190401-记录一次bug ConstraintViolationException
    new Date()的浏览器兼容性问题
    单例模式(转)
    SQL Server使用一个语句块批量插入多条记录的三种方法和union和union all区别
  • 原文地址:https://www.cnblogs.com/rikurika/p/12022416.html
Copyright © 2020-2023  润新知