洛谷P3227 [HNOI2013]切糕
作者:互联网
题目大意:
一个立方体,每个点一个点权,要求从每个竖轴上选一个点使得点权之和最小
特殊限制:当在某一条竖轴上选择了点\((x,y,z)\)时,与其相邻的竖轴上选择的点纵坐标绝对值相差不能超过\(d\)
哭哭,不会,颓了吴迪的博客
看见点权和最小先想的是最小费用最大流/总点权-最大流,结果是个硬核最小割……
考虑每条竖轴上的点只能选择一个,把每条竖轴串联
考虑相邻竖轴必须选某段区间内的点,把每个点和相邻竖轴所在区间并联
吴迪牛逼
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
namespace red{
#define eps (1e-8)
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=50*50*50,inf=0x3f3f3f3f;
int n,m,h,dis,st,ed;
int dx[4]={0,-1,0,1},dy[4]={1,0,-1,0};
int head[N],cur[N],cnt=1;
struct point
{
int nxt,to,val;
point(){}
point(const int &nxt,const int &to,const int &val):nxt(nxt),to(to),val(val){}
}a[N<<3];
inline void link(int x,int y,int z)
{
a[++cnt]=(point){head[x],y,z};head[x]=cnt;
a[++cnt]=(point){head[y],x,0};head[y]=cnt;
}
int d[N];
queue<int> q;
inline bool bfs()
{
for(int i=1;i<=n*m*h+2;++i) cur[i]=head[i],d[i]=0;
q.push(st);d[st]=1;
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=head[now];i;i=a[i].nxt)
{
int t=a[i].to;
if(!d[t]&&a[i].val)
{
d[t]=d[now]+1;
q.push(t);
}
}
}
return d[ed];
}
inline int dfs(int now,int c)
{
if(now==ed||!c) return c;
int ret=c,f;
for(int i=cur[now];i;i=a[i].nxt)
{
cur[now]=i;
int t=a[i].to;
if(d[t]==d[now]+1)
{
f=dfs(t,min(a[i].val,ret));
a[i].val-=f;
a[i^1].val+=f;
ret-=f;
if(!ret) return c;
}
}
if(ret==c) d[now]=0;
return c-ret;
}
inline int dinic()
{
int ret=0;
while(bfs()) ret+=dfs(st,inf);
return ret;
}
inline int pos(int k,int i,int j)
{
return (k-1)*(n*m)+(i-1)*m+j;
}
inline void main()
{
n=read(),m=read(),h=read();
dis=read();
st=n*m*h+1,ed=n*m*h+2;
for(int x,k=1;k<=h;++k)
{
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
x=read();
if(k==1) link(st,pos(1,i,j),x),link(pos(h,i,j),ed,inf);
else link(pos(k-1,i,j),pos(k,i,j),x);
for(int t=0;t<4;++t)
{
int tx=i+dx[t],ty=j+dy[t];
if(tx<1||tx>n||ty<1||ty>m) continue;
if(k-dis>=1) link(pos(k,i,j),pos(k-dis,tx,ty),inf);
if(k+dis<=h) link(pos(k+dis,tx,ty),pos(k,i,j),inf);
}
}
}
}
printf("%d\n",dinic());
}
}
signed main()
{
red::main();
return 0;
}
标签:切糕,P3227,int,dis,竖轴上,HNOI2013,ch,include,getchar 来源: https://www.cnblogs.com/knife-rose/p/12100211.html