题目描述

最近在生物实验室工作的小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中的最小 者。)

输入输出格式

输入格式:

第一行是一个正整数D,表示数据组数。接下来是D组数据,每组数据开头是三个数a,b,c表示实验皿的尺寸。接下来会出现a个b 行c列的用空格隔开的01矩阵,0表示对应的单位立方体不要求消毒,1表示对应的单位立方体需要消毒;例如,如果第1个01矩阵的第2行第3列为1,则表示单位立方体(1,2,3)需要被消毒。输入保证满足a*b*c<=5000,T<=3。

输出格式:

仅包含D行,每行一个整数,表示对应实验皿最少要用多少单位 的F试剂。

输入输出样例

输入样例#1: 复制

1
4 4 4
1 0 1 1
0 0 1 1
0 0 0 0
0 0 0 0
0 0 1 1
1 0 1 1
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
1 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
1 0 0 0
输出样例#1: 复制

3

说明

对于区域(1,1,3)-(2,2,4)和(1,1,1)-(4,4,1)消毒,分别花费2个单位和1个单位的F试剂。

题解

  我们先来考虑一下二维的情况

  对于一整块需要染色的部分,我们可以选择一条一条地去染色(也就是说使每一次的最小值为$1$,另一个就可以随便取了),那么答案肯定不会比直接一块染更差

  比方说$(1,1)$到$(2,3)$都有,你直接整块染或者每次染一行实际上答案是一样的

  所以我们对每一个点的$x->y$连一条边,然后要求一个最小点覆盖,等于最大匹配

  然后怎么考虑三维的情况?我们可不会三分图,那个可没有多项式解法

  考虑到$a,b,c$中最小的不会超过17(因为$17^3=4913$),所以我们可以考虑枚举这一维,枚举每一层是否直接切掉

  剩下没有切的层已经是一个二维的情况了,可以直接用二分图跑

  ps:我抄借鉴代码的时候有很多细节问题不明白,比如二分图为什么可以不用拆成左右两边的点,可以在一排点里直接连。后来发现是因为右边的点有用的只有它与哪个左部点匹配,所以只需要一排点也可以记录这些信息(因为我二分图根本没学过所以理解起来很吃力……以前都是直接用网络流跑的从来没去了解过匈牙利……)

 //minamoto
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,:;}
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
const int N=;
int head[N],Next[N],ver[N],edge[N],Pre[N],vis[N],tot;
int sx[][N],a,b,c,ans,st[N],num,mn;
inline void add(int u,int v){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
}
bool dfs(int u){
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(!vis[v]){
vis[v]=true;
if(!Pre[v]||dfs(Pre[v])){
Pre[v]=u;return true;
}
}
}
return false;
}
void work(int x){
memset(head,,sizeof(head));
memset(Pre,,sizeof(Pre));
tot=;
int tmp=;
for(int i=;i<a;++i){
if(x&(<<i)) st[i+]=false,++tmp;
else st[i+]=true;
}
for(int i=;i<=num;++i)
if(st[sx[][i]]) add(sx[][i],sx[][i]);
for(int i=;i<=b;++i){
for(int j=;j<=c;++j) vis[j]=false;
if(dfs(i)) ++tmp;
}
cmin(ans,tmp);
}
int main(){
int T=read();
while(T--){
num=,ans=inf;
a=read(),b=read(),c=read();
mn=min(a,min(b,c));
for(int i=;i<=a;++i)
for(int j=;j<=b;++j)
for(int k=;k<=c;++k){
int u=read();
if(!u) continue;
sx[][++num]=i;
sx[][num]=j;
sx[][num]=k;
}
if(mn==b) swap(a,b),swap(sx[],sx[]);
else if(mn==c) swap(a,c),swap(sx[],sx[]);
for(int i=;i<(<<a);++i) work(i);
printf("%d\n",ans);
}
return ;
}

bzoj3140: [Hnoi2013]消毒(二分图)的更多相关文章

  1. [BZOJ3140][HNOI2013]消毒(二分图最小点覆盖)

    3140: [Hnoi2013]消毒 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1621  Solved: 676[Submit][Status] ...

  2. [BZOJ3140][HNOI2013]消毒:二分图匹配

    分析 假如实验皿是二维的,那么这道题便是一个二分图最小点覆盖问题,可以转化为二分图最大匹配问题,使用匈牙利算法解决. 考虑如何扩展到三维,首先我们发现一次操作的代价为\(min(x,y,z)\).不难 ...

  3. bzoj3140: [Hnoi2013]消毒

    Description 最近在生物实验室工作的小T遇到了大麻烦. 由于实验室最近升级的缘故,他的分格实验皿是一个长方体,其尺寸为a*b*c,a.b.c 均为正整数.为了实验的方便,它被划分为a*b*c ...

  4. [luogu3231 HNOI2013] 消毒 (二分图最小点覆盖)

    传送门 Description 最近在生物实验室工作的小T遇到了大麻烦. 由于实验室最近升级的缘故,他的分格实验皿是一个长方体,其尺寸为abc,a.b.c 均为正整数.为了实验的方便,它被划分为abc ...

  5. BZOJ.3140.[HNOI2013]消毒(二分图匹配 匈牙利)

    题目链接 不难想到每次一定是切一片. 如果是平面,很容易想到直接做二分图匹配.对于3维的? 可以发现min(a,b,c)的最大值只有\(\sqrt[3]{n}≈17\),我们暴力枚举这一最小值代表的是 ...

  6. bzoj千题计划295:bzoj3140: [Hnoi2013]消毒

    http://www.lydsy.com/JudgeOnline/problem.php?id=3140 如果只有两维,那就是二分图最小点覆盖 现在是三维,但是a*b*c<=5000,说明最小的 ...

  7. [HNOI2013] 消毒 - 二分图匹配

    容易发现 \(a,b,c\) 中至少有一个 \(\leq 17\) 不妨将其调剂为 \(a\),那么我们可以暴力枚举哪些 \(x\) 片片要被直接削掉,剩下的拍扁成二维情况 二维时,如果有一个格子是 ...

  8. 【BZOJ3140】消毒(二分图匹配)

    [BZOJ3140]消毒(二分图匹配) 题面 Description 最近在生物实验室工作的小T遇到了大麻烦. 由于实验室最近升级的缘故,他的分格实验皿是一个长方体,其尺寸为abc,a.b.c 均为正 ...

  9. P3231 [HNOI2013]消毒

    P3231 [HNOI2013]消毒 二维覆盖我们已经很熟悉了 扩展到三维,枚举其中较小的一维,这里定义为$a$ 以$a$为关键字状压,$1$表示该面全选 剩下的面和二维覆盖一样二分图匹配 如果还没接 ...

随机推荐

  1. js生成邀请码(1)

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  2. css3弹性布局语法全解

    本文介绍css3弹性布局的语法 html布局 <div class="box"> <div class="item">1</div ...

  3. php学习之try catch

    PHP 5 添加了类似于其它语言的异常处理模块.在 PHP 代码中所产生的异常可被 throw语句抛出并被 catch 语句捕获.(注:一定要先抛才能获取) 需要进行异常处理的代码都必须放入 try ...

  4. HDLM命令dlnkmgr详解之二__help/clear

    1.help操作 主要显示命令的帮助信息. 显示所有操作的帮助信息 -bash-3.2# dlnkmgr help dlnkmgr: Format dlnkmgr { clear | help | o ...

  5. Go并发原理

    Go语言是为并发而生的语言,Go语言是为数不多的在语言层面实现并发的语言:也正是Go语言的并发特性,吸引了全球无数的开发者. 并发(concurrency)和并行(parallellism) 并发(c ...

  6. TCP/IP 笔记 7 Ping

    lenovo-myc@lenovomyc-Lenovo-Product:~$ ping www.baidu.com PING www.a.shifen.com (() bytes of data. 这 ...

  7. 【Android异常】The specified child already has a parent. You must call removeView() on the child's parent first.

    错误信息: Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must ...

  8. javascript作用域原理

    问题的提出 首先看一个例子: var name = 'laruence'; function echo() { alert(name); var name = 'eve'; alert(name); ...

  9. Ajax入门(二)Ajax函数封装

    如果看了的我上一篇博客<Ajax入门(一)从0开始到一次成功的GET请求>的话,肯定知道我们已经完成了一个简单的get请求函数了.如下: 1234567891011121314151617 ...

  10. REST API (更新文档)

    Elasticsearch的更新文档API准许通过脚本操作来更新文档.更新操作从索引中获取文档,执行脚本,然后获得返回结果.它使用版本号来控制文档获取或者重建索引. 我们新建一个文档: 请求:PUT  ...