3144: [Hnoi2013]切糕 思路题 最小割
2016-01-22 09:58
441 查看
sb不认真读题+sb的脑补能力。。
居然以为切面一定是平面。。居然以为x,y坐标可以不是整数。。
回正题。。qwq
本题可以想象成一个矩阵,每个矩阵有一些值可以取,要求相邻格子的差不能超过D。
那么我们可以按高度分层建图,即每一个点,c(i,j,k-1)->c(i,j,k),然后高度差的问题,c(i,j,k)->c(x,y,k-d)。跑最小割就好了。
居然以为切面一定是平面。。居然以为x,y坐标可以不是整数。。
回正题。。qwq
本题可以想象成一个矩阵,每个矩阵有一些值可以取,要求相邻格子的差不能超过D。
那么我们可以按高度分层建图,即每一个点,c(i,j,k-1)->c(i,j,k),然后高度差的问题,c(i,j,k)->c(x,y,k-d)。跑最小割就好了。
#include<iostream> #include<cstdio> #include<cstring> #define N 100005 #define inf 1000000007 using namespace std; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; int P,Q,R,D,T,cnt=1; int cur ,head ,dis ,q ; int next[10*N],list[10*N],key[10*N]; int f[41][41][41]; inline int read() { int a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } inline bool BFS() { memset(dis,-1,sizeof(dis)); dis[0]=1; q[1]=0; int t=0,w=1,x; while (t<w) { x=q[++t]; for (int i=head[x];i;i=next[i]) if (key[i]&&dis[list[i]]==-1) dis[list[i]]=dis[x]+1,q[++w]=list[i]; } return dis[T]!=-1; } int find(int x,int flow) { if (x==T) return flow; int w,used=0; for (int i=cur[x];i;i=next[i]) if (key[i]&&dis[list[i]]==dis[x]+1) { w=find(list[i],min(key[i],flow-used)); key[i]-=w; key[i^1]+=w; used+=w; if (used==flow) return used; } if (!used) dis[x]=-1; return used; } inline int dinic() { int tmp=0; while (BFS()) { for (int i=0;i<=T;i++) cur[i]=head[i]; tmp+=find(0,inf); } return tmp; } inline void insert(int x,int y,int z) { next[++cnt]=head[x]; head[x]=cnt; list[cnt]=y; key[cnt]=z; } inline int c(int x,int y,int z) { if (!z) return 0; return (z-1)*P*Q+(x-1)*Q+y; } inline void build() { for (int i=1;i<=P;i++) for (int j=1;j<=Q;j++) { for (int k=1;k<=R;k++) { insert(c(i,j,k-1),c(i,j,k),f[i][j][k]); insert(c(i,j,k),c(i,j,k-1),0); if (k>D) for (int l=0;l<4;l++) { int x=i+dx[l],y=j+dy[l]; if (x<1||x>P||y<1||y>Q) continue; insert(c(i,j,k),c(x,y,k-D),inf); insert(c(x,y,k-D),c(i,j,k),0); } } insert(c(i,j,R),T,inf); insert(T,c(i,j,R),0); } } int main() { P=read(); Q=read(); R=read(); D=read(); 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++) f[j][k][i]=read(); build(); cout << dinic() << endl; return 0; }
相关文章推荐
- J - Dungeon Master poj2251
- C++使用STL::vector删除数组内的重复元素
- centos 安装软件
- iOS开发笔记--将图片设置为主界面背景
- “一日游”
- PHP中new static()与new self()的区别异同
- HTTP protocal
- qt 通过样式表修改背景
- openstack dashboard实例连接失败的解决办法
- 关于MyEclipse8.5 错误 background indexer crash recovery java.lang.stackoverflowerror
- 垃圾收集器与内存分配策略——对象的生命、垃圾收集算法
- iOS开发笔记--调用iPhone的短信、地图、电话、邮件、浏览器
- Modbus通讯协议学习 - 认识篇
- apache traffic server6.0 安装
- swift学习及感受
- 深入浅出外观模式(一):外观模式概述,外观模式结构与实现
- linux(所有版本)下安装有道词典
- web页面化工作的前期基础学习(三)——HTML标签事件
- Java设计模式四: 原型模式(Prototype Pattern)
- iOS开发笔记--NSString字符串处理