[HNOI2013]消毒 (匈牙利最大匹配)
Description
最近在生物實(shí)驗(yàn)室工作的小T遇到了大麻煩。
由于實(shí)驗(yàn)室最近升級(jí)的緣故,他的分格實(shí)驗(yàn)皿是一個(gè)長方體,其尺寸為abc,a、b、c 均為正整數(shù)。為了實(shí)驗(yàn)的方便,它被劃分為abc個(gè)單位立方體區(qū)域,每個(gè)單位立方體尺寸為111。用(i,j,k)標(biāo)識(shí)一個(gè)單位立方體,1 ≤i≤a,1≤j≤b,1≤k≤c。這個(gè)實(shí)驗(yàn)皿已經(jīng)很久沒有人用了,現(xiàn)在,小T被導(dǎo)師要求將其中一些單位立方體區(qū)域進(jìn) 行消毒操作(每個(gè)區(qū)域可以被重復(fù)消毒)。而由于嚴(yán)格的實(shí)驗(yàn)要求,他被要求使用一種特定 的F試劑來進(jìn)行消毒。 這種F試劑特別奇怪,每次對(duì)尺寸為xyz的長方體區(qū)域(它由xyz個(gè)單位立方體組 成)進(jìn)行消毒時(shí),只需要使用min{x,y,z}單位的F試劑。F試劑的價(jià)格不菲,這可難倒了小 T。現(xiàn)在請(qǐng)你告訴他,最少要用多少單位的F試劑。(注:min{x,y,z}表示x、y、z中的最小 者。)
Input
第一行是一個(gè)正整數(shù)D,表示數(shù)據(jù)組數(shù)。接下來是D組數(shù)據(jù),每組數(shù)據(jù)開頭是三個(gè)數(shù)a,b,c表示實(shí)驗(yàn)皿的尺寸。接下來會(huì)出現(xiàn)a個(gè)b 行c列的用空格隔開的01矩陣,0表示對(duì)應(yīng)的單位立方體不要求消毒,1表示對(duì)應(yīng)的單位立方體需要消毒;例如,如果第1個(gè)01矩陣的第2行第3列為1,則表示單位立方體(1,2,3)需要被消毒。輸入保證滿足abc≤5000,T≤3。
Output
僅包含D行,每行一個(gè)整數(shù),表示對(duì)應(yīng)實(shí)驗(yàn)皿最少要用多少單位 的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
對(duì)于區(qū)域(1,1,3)-(2,2,4)和(1,1,1)-(4,4,1)消毒,分別花費(fèi)2個(gè)單位和1個(gè)單位的F試劑
solution
抽絲剝繭
先思考在二維平面消毒時(shí),怎么做??
顯然,是行列二分圖跑最大匹配的板
那么將這個(gè)搬到三維,可咱不會(huì)三位最大匹配啊!
abc≤500abc\le500abc≤500,所以至少有一個(gè)是<17<17<17的
又可以考慮狀壓了
假設(shè)a,b,ca,b,ca,b,c中最小的為aaa
那么枚舉狀態(tài),如果二進(jìn)制對(duì)應(yīng)位為111,表示直接把這一層給削去
厚度為111的消毒劑可以做到
剩下的沒有削的層,拍扁成二維平面跑最大匹配
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; }總結(jié)
以上是生活随笔為你收集整理的[HNOI2013]消毒 (匈牙利最大匹配)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 文理分科 (最小割问题)
- 下一篇: [NOI2009] 变换序列 (匈牙利最