bzoj 3140: [Hnoi2013]消毒 dfs+网络流
来源:互联网 发布:淘宝照片拍摄技巧 编辑:程序博客网 时间:2024/04/29 04:40
题意
最近在生物实验室工作的小T遇到了大麻烦。
由于实验室最近升级的缘故,他的分格实验皿是一个长方体,其尺寸为a*b*c,a、b、c 均为正整数。为了实验的方便,它被划分为a*b*c个单位立方体区域,每个单位立方体尺寸
为1*1*1。用(i,j,k)标识一个单位立方体,1 ≤i≤a,1≤j≤b,1≤k≤c。这个实验皿已经很久没有人用了,现在,小T被导师要求将其中一些单位立方体区域进 行消毒操作(每个区域可以被重复消毒)。而由于严格的实验要求,他被要求使用一种特定 的F试剂来进行消毒。 这种F试剂特别奇怪,每次对尺寸为x*y*z的长方体区域(它由x*y*z个单位立方体组 成)进行消毒时,只需要使用min{x,y,z}单位的F试剂。F试剂的价格不菲,这可难倒了小 T。现在请你告诉他,最少要用多少单位的F试剂。(注:min{x,y,z}表示x、y、z中的最小 者。)
a*b*c≤5000,T≤3
分析
首先考虑二维下的情况,显然最优的一定是每次选择一整行或一整列来清理。那么只要一个最小点覆盖就可以解决了。也就是对于每一个要清洗的点(x,y),往第x行和第y列连边,那么最大流就是答案。
推广到三维,显然每次选择一个平面内的点清洗是最优的。。。然后我就不会了2333
其实我们还是可以强行把三维转换成二维模型。考虑a*b*c<=5000,那么必然有min(a,b,c)<=17,假设a<=b<=c,那么我们可以强行O(2^a)枚举我们要清洗哪些平面,然后再用二维的方法去解决就好了。
第一次把网络流写到struct里面耶,居然还就1A了。真的开心~
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int N=5005;const int inf=0x3f3f3f3f;int a,b,c,ans,tot;struct data{int x,y,z;}f[N];bool vis[N],con[N][N];int read(){ 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;}struct Max_flow{ int cnt,last[N],s,t,cur[N],dis[N]; struct edge{int to,c,next;}e[N*100]; queue<int> q; void clear() { cnt=1; for (int i=s;i<=t;i++) last[i]=0; } void addedge(int u,int v,int c) { e[++cnt].to=v;e[cnt].c=c;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].c=0;e[cnt].next=last[v];last[v]=cnt; } bool bfs() { for (int i=s;i<=t;i++) dis[i]=0; while (!q.empty()) q.pop(); dis[s]=1;q.push(s); while (!q.empty()) { int u=q.front();q.pop(); for (int i=last[u];i;i=e[i].next) if (e[i].c&&!dis[e[i].to]) { dis[e[i].to]=dis[u]+1; if (e[i].to==t) return 1; q.push(e[i].to); } } return 0; } int dfs(int x,int maxf) { if (x==t||!maxf) return maxf; int ret=0; for (int &i=cur[x];i;i=e[i].next) if (e[i].c&&dis[e[i].to]==dis[x]+1) { int f=dfs(e[i].to,min(e[i].c,maxf-ret)); e[i].c-=f; e[i^1].c+=f; ret+=f; if (maxf==ret) break; } return ret; } int dinic() { int ans=0; while (bfs()) { for (int i=s;i<=t;i++) cur[i]=last[i]; ans+=dfs(s,inf); } return ans; }}flow;int solve(){ flow.s=0;flow.t=b+c+1; flow.clear(); for (int i=1;i<=tot;i++) if (!vis[f[i].x]&&!con[f[i].y][f[i].z]) con[f[i].y][f[i].z]=1,flow.addedge(f[i].y,f[i].z+b,1); for (int i=1;i<=tot;i++) con[f[i].y][f[i].z]=0; for (int i=1;i<=b;i++) flow.addedge(flow.s,i,1); for (int i=1;i<=c;i++) flow.addedge(i+b,flow.t,1); return flow.dinic();}void dfs(int x,int y){ if (x>a) { ans=min(ans,y+solve()); return; } dfs(x+1,y); vis[x]=1; dfs(x+1,y+1); vis[x]=0;}int main(){ int T=read(); while (T--) { a=read();b=read();c=read(); tot=0;ans=a*b*c; for (int i=1;i<=a;i++) for (int j=1;j<=b;j++) for (int k=1;k<=c;k++) { int x=read(); if (x) f[++tot].x=i,f[tot].y=j,f[tot].z=k; } if (b<a&&b<c) { swap(a,b); for (int i=1;i<=tot;i++) swap(f[i].x,f[i].y); } else if (c<a&&c<b) { swap(a,c); for (int i=1;i<=tot;i++) swap(f[i].x,f[i].z); } dfs(1,0); printf("%d\n",ans); }}
阅读全文
0 0
- bzoj 3140: [Hnoi2013]消毒 dfs+网络流
- 【BZOJ 3140】 [Hnoi2013]消毒
- BZOJ 3140 [HNOI2013]消毒
- BZOJ 3140: [Hnoi2013]消毒
- [Hnoi2013]消毒
- 【HNOI2013】消毒
- [bzoj3140][HNOI2013]消毒
- bzoj3140: [Hnoi2013]消毒
- BZOJ3140 HNOI2013消毒
- BZOJ3140: [Hnoi2013]消毒
- 【bzoj3140】[Hnoi2013]消毒
- HNOI 2013 bzoj 3140 消毒
- Bzoj3140:[Hnoi2013]消毒:二分图
- bzoj3140 hnoi2013 消毒(暴力出奇迹)
- bzoj3140: [Hnoi2013]消毒 二分图匹配
- [BZOJ3144][HNOI2013]切糕-网络流
- [bzoj3144] [HNOI2013]切糕 网络流最小割
- 【bzoj 3142】: [Hnoi2013]数列
- phonegap环境准备
- ios自定义键盘
- MongoDB基础配置及权限配置
- VM12安装centos
- 控件问题
- bzoj 3140: [Hnoi2013]消毒 dfs+网络流
- C++静态库与动态库区别
- 《程序调试思想与实践》.(The.Science.of.Debugging)读书笔记
- ios 转场动画
- Promise对象详解
- Andriod系统程序监听SD卡的插拔
- dvm 与jvm 区别
- 分享一个GitHub 上的控件:MaterialEditText 详解
- Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3) C. Success Rate(数学,二分)