[bzoj3140][二分图匹配]消毒

版权声明:蒻蒟的bolg... https://blog.csdn.net/Rose_max/article/details/85264449

Description

最近在生物实验室工作的小T遇到了大麻烦。 由于实验室最近升级的缘故,他的分格实验皿是一个长方体,其尺寸为abc,a、b、c
均为正整数。为了实验的方便,它被划分为abc个单位立方体区域,每个单位立方体尺寸 为111。用(i,j,k)标识一个单位立方体,1
≤i≤a,1≤j≤b,1≤k≤c。这个实验皿已经很久没有人用了,现在,小T被导师要求将其中一些单位立方体区域进
行消毒操作(每个区域可以被重复消毒)。而由于严格的实验要求,他被要求使用一种特定 的F试剂来进行消毒。
这种F试剂特别奇怪,每次对尺寸为xyz的长方体区域(它由xyz个单位立方体组
成)进行消毒时,只需要使用min{x,y,z}单位的F试剂。F试剂的价格不菲,这可难倒了小
T。现在请你告诉他,最少要用多少单位的F试剂。(注:min{x,y,z}表示x、y、z中的最小 者。)

Input

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

Output

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

Sample Input

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

Sample Output

3

HINT

对于区域(1,1,3)-(2,2,4)和(1,1,1)-(4,4,1)消毒,分别花费2个单位和1个单位的F试剂。2017.5.26新加两组数据By
Leoly,未重测.

题解

wori拍扁到二维居然都不是很会做啊…
容易发现 对于任意一种解法,我们都可以把它分割成 ( 1 , y ) (1,y) 或者 ( x , 1 ) (x,1) 的矩阵
所以二维就可以直接 x > y x->y 二分图匹配了
三维的话…
发现最小的那一维肯定不会超过17
又发现在这种情况下肯定是每次消毒一个截面
暴力枚举最小那一维怎么消毒
然后就全部拍扁到二维,二分图玩一玩就行了…
有点卡常…

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline int read()
{
	int f=1,x=0;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;
}
int stack[20];
inline void write(int x)
{
	if(x<0){putchar('-');x=-x;}
    if(!x){putchar('0');return;}
    int top=0;
    while(x)stack[++top]=x%10,x/=10;
    while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(int x){write(x);putchar('\n');}
const int MAXN=10005;
const int MAXM=500005;
struct edge{int x,y,next;}a[MAXM];int len,last[MAXN];
void ins(int x,int y){len++;a[len].x=x;a[len].y=y;a[len].next=last[x];last[x]=len;}
int chw[MAXN],tim,match[MAXN],ok[MAXN],t1;
bool findmuniu(int x)
{
	for(int k=last[x];k;k=a[k].next)
	{
		int y=a[k].y;
		if(chw[y]!=tim)
		{
			chw[y]=tim;
			if(ok[y]!=t1||findmuniu(match[y]))
			{
				match[y]=x;ok[y]=t1;
				return true;
			}
		}
	}
	return false;
}
//vector<int> vec[20][5005];//z x y
int A,B,C,cl[20],ans;
struct pt
{
	int x,y,z;
	pt(){}
	pt(int _x,int _y,int _z){x=_x;y=_y;z=_z;}
}g[MAXN];int le;
int fir[20];
void solve(int s1)
{
	if(A<B)
	{
		len=0;for(int i=1;i<=A;i++)last[i]=0;
		for(int i=1;i<=19;i++)if(fir[i]<=1e9&&!cl[i])
		{
			for(int j=fir[i];j<=le;j++)
			{
				if(g[j].z!=i)break;
				ins(g[j].x,g[j].y+A);
			}
		}
//		for(int i=1;i<=le;i++)if(!cl[g[i].z])ins(g[i].x,g[i].y+A);
		t1++;
		int re=0;
		for(int i=1;i<=A;i++)
		{
			tim++;
			if(findmuniu(i))re++;
			if(re+s1>=ans)return ;
		}
		ans=min(ans,re+s1);
	}
	else
	{
		len=0;for(int i=1;i<=B;i++)last[i]=0;
		for(int i=1;i<=19;i++)if(fir[i]<=1e9&&!cl[i])
		{
			for(int j=fir[i];j<=le;j++)
			{
				if(g[j].z!=i)break;
				ins(g[j].y,g[j].x+B);
			}
		}
//		for(int i=1;i<=le;i++)if(!cl[g[i].z])ins(g[i].y,g[i].x+B);
		t1++;
		int re=0;
		for(int i=1;i<=B;i++)
		{
			tim++;
			if(findmuniu(i))re++;
			if(re+s1>=ans)return ;
		}
		ans=min(ans,re+s1);
	}
}
void dfs(int k,int to)
{
	if(to>ans)return ;
	if(k==C+1){solve(to);return ;}
	dfs(k+1,to);
	cl[k]=1;dfs(k+1,to+1);cl[k]=0;
}
bool cmp(pt n1,pt n2){return n1.z<n2.z;}
int main()
{
//	freopen("10.in","r",stdin);
	int T=read();
	while(T--)
	{
		A=read();B=read();C=read();int gg=min(A,min(B,C));le=0;
		if(gg==A)
		{
			for(int i=1;i<=A;i++)for(int j=1;j<=B;j++)for(int k=1;k<=C;k++)
			{
				int c=read();
				if(c)g[++le]=pt(k,j,i);
			}
			int u1=C,u2=B,u3=A;
			A=u1;B=u2;C=u3;
		}
		else if(gg==B)
		{
//			for(int i=1;i<=A;i++)for(int j=1;j<=B;j++)for(int k=1;k<=C;k++)vec[j][i].push_back(read());
			for(int i=1;i<=A;i++)for(int j=1;j<=B;j++)for(int k=1;k<=C;k++)
			{
				int c=read();
				if(c)g[++le]=pt(i,k,j);
			}
			int u1=A,u2=C,u3=B;
			A=u1;B=u2;C=u3;
		}
		else
		{
			for(int i=1;i<=A;i++)for(int j=1;j<=B;j++)for(int k=1;k<=C;k++)
			{
				int c=read();
				if(c)g[++le]=pt(i,j,k);
			}
			int u1=A,u2=B,u3=C;
			A=u1;B=u2;C=u3;
		}
//		for(int i=1;i<=C;i++)
//		{
//			for(int j=1;j<=A;j++)
//			{
//				for(int k=0;k<B;k++)pr1(vec[i][j][k]);
//				puts("");
//			}
//			puts("");
//		}
		sort(g+1,g+1+le,cmp);
		memset(fir,63,sizeof(fir));
		for(int i=1;i<=le;i++)fir[g[i].z]=min(fir[g[i].z],i);
		ans=999999999;dfs(1,0);

		pr2(ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Rose_max/article/details/85264449