[HNOI2013] Disinfection (Hungarian biggest match)

Description

Recently, Little T, who works in the biological laboratory, ran into big troubles.
Due to the recent upgrade of the laboratory, his compartmentalized test vessel is a cuboid with dimensions a b c, and a, b, and c are all positive integers. For the convenience of the experiment, it is divided into a b c unit cube areas, and each unit cube has a size of 1 1 1. Use (i,j,k) to identify a unit cube, 1≤i≤a, 1≤j≤b, 1≤k≤c. This experimental dish has not been used for a long time. Now, Xiao T is asked by his instructor to disinfect some of the unit cube areas (each area can be disinfected repeatedly). Due to strict experimental requirements, he was required to use a specific F reagent for disinfection. This kind of F reagent is particularly strange. When disinfecting a rectangular parallelepiped area (which consists of x y z unit cubes) with a size of x y z , you only need to use the F reagent of min{x,y,z} units. The price of F reagent is expensive, which can stump the little T. Now please tell him how many units of F reagent should be used at least. (Note: min{x,y,z} means the smallest of x, y, z.)

The
first line of Input is a positive integer D, which represents the number of data groups. Next is the D group of data. At the beginning of each group of data are three numbers a, b, and c representing the size of the experiment vessel. Next, there will be a 01 matrix separated by a space in b rows and c columns. 0 means that the corresponding unit cube does not require disinfection, and 1 means that the corresponding unit cube needs to be disinfected; for example, if the first 01 matrix is ​​the second row The third column is 1, which means that the unit cube (1,2,3) needs to be disinfected. The input is guaranteed to satisfy a b c≤5000, T≤3.

Output
only contains D rows, and each row has an integer, which indicates how many units of F reagent should be used in the corresponding experiment dish.

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
disinfects the areas (1,1,3)-(2,2,4) and (1,1,1)-(4,4,1), which costs 2 units and 1 unit of F reagent, respectively

solution

Unraveling the
first thought in the two-dimensional plane disinfected, how do? ?
Obviously, it is the board with the largest match in the row-column bipartite graph run

Then move this to 3D, but we won't be the three biggest matches!
Insert picture description here
abc ≤ 500 abc\le500abc5 0 0 , so at least one is<17 <17<. 1 . 7 is
another conceivable shaped pressed
Insert picture description here
assumea, b, ca, b,a,b,The smallest in c isaaa
Then enumerate status, if the binary corresponding bit is1 11 , means to cut off this layer directly, the
thickness is1 1The disinfectant of 1 can do the
remaining uncut layer, flatten it into a two-dimensional plane and run the maximum matching

code

#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
#define maxn 5005
vector < int > G[maxn];
int D, a, b, c, ans, tot;
int match[maxn];
int virus[4][maxn];
bool vis[maxn], flag[maxn];

bool find( int u ) {
    
    
	for( int i = 0;i < G[u].size();i ++ ) {
    
    
		int v = G[u][i];
		if( vis[v] ) continue;
		vis[v] = 1;
		if( ! match[v] || find( match[v] ) ) {
    
    
			match[v] = u;
			return 1;
		}
	}
	return 0;
}

void solve( int s ) {
    
    
	memset( match, 0, sizeof( match ) );
	for( int i = 1;i <= b;i ++ ) G[i].clear();
	int cnt = 0;
	for( int i = 0;i < a;i ++ )
		if( ( 1 << i ) & s ) flag[i + 1] = 0, cnt ++;
		else flag[i + 1] = 1;
	for( int i = 1;i <= tot;i ++ )
		if( flag[virus[1][i]] ) G[virus[2][i]].push_back( virus[3][i] );
	for( int i = 1;i <= b;i ++ ) {
    
    
		memset( vis, 0, sizeof( vis ) );
		if( find( i ) ) cnt ++;
	}
	ans = min( ans, cnt );
}

int main() {
    
    
	scanf( "%d", &D );
	while( D -- ) {
    
    
		tot = 0, ans = 0x7f7f7f7f;
		scanf( "%d %d %d", &a, &b, &c );
		for( int i = 1;i <= a;i ++ )
			for( int j = 1;j <= b;j ++ )
				for( int k = 1, x;k <= c;k ++ ) {
    
    
					scanf( "%d", &x );
					if( ! x ) continue;
					++ tot;
					virus[1][tot] = i;
					virus[2][tot] = j;
					virus[3][tot] = k;
				}
		int minn = min( a, min( b, c ) );
		if( minn == b ) swap( a, b ), swap( virus[1], virus[2] );
		else if( minn == c ) swap( a, c ), swap( virus[1], virus[3] );
		for( int i = 0;i < ( 1 << a );i ++ )
			solve( i );
		printf( "%d\n", ans );
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/Emm_Titan/article/details/113700560