【BZOJ】3140: [Hnoi2013]消毒

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3140


 

猜一发(显然)有结论:每次一定选择一个平面,即每次操作对答案的贡献都为$1$

首先可以考虑二维的情况。

二维不就是一个经典的最小点覆盖模型么,如果${(x,y)=1}$就把横纵轴上的点分别看为二分图的两边的点,最小点覆盖模型=最大匹配数。

三维?

${a*b*c<=5000}$显然${Max\left \{ a,b,c \right \}<=17}$
考虑枚举(搜索)最小的那一维,剩下的直接看(拍)成一个平面当成二维的做即可。


 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<cstring>
 8 using namespace std;
 9 #define maxn 1000100
10 #define llg long long 
11 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
12 llg n,G,C,K,T,cnt,N,belong[maxn],bj[maxn];
13 
14 vector<llg>a[maxn];
15 
16 struct node
17 {
18     llg x,y,z;
19 }point[maxn];
20 
21 void init()
22 {
23     llg x;
24     cnt=0;
25     scanf("%lld%lld%lld",&C,&K,&G);
26     for (llg i=1;i<=C;i++)
27         for (llg j=1;j<=K;j++)
28             for (llg k=1;k<=G;k++)
29             {
30                 scanf("%lld",&x);
31                 if (x) point[++cnt]=(node){i,j,k}; 
32             }
33 }
34 
35 bool find(llg x)
36 {
37     llg w=a[x].size(),v;
38     for (llg i=0;i<w;i++)
39     {
40         v=a[x][i];
41         if (bj[v]) continue;
42         bj[v]=1;
43         if (!belong[v] || find(belong[v]))
44         {
45             belong[v]=x; belong[x]=v;
46             return 1;
47         }
48     }
49     return 0;
50 }
51 
52 llg work(llg zt)
53 {
54     llg sum=0; N=C+K;
55     for (llg i=1;i<=N;i++) a[i].clear(),belong[i]=0;
56     for (llg i=0;i<G;i++) if ((zt&(1<<i))==0) sum++;
57     for (llg i=1;i<=cnt;i++)
58         if (zt&(1<<(point[i].z-1)))
59         {
60             llg x=point[i].x,y=C+point[i].y;
61             a[x].push_back(y),a[y].push_back(x);
62         }
63     for (llg i=1;i<=N;i++) 
64         if (!belong[i])
65         {
66             for (llg j=1;j<=N;j++) bj[j]=0; 
67             if (find(i)) sum++;
68         }
69     return sum;
70 }
71 
72 int main()
73 {
74     yyj("clear");
75     cin>>T;
76     while (T--)
77     {
78         init();
79         if (C<G) {swap(G,C); for (llg i=1;i<=cnt;i++) swap(point[i].x,point[i].z); }
80         if (K<G) {swap(G,K); for (llg i=1;i<=cnt;i++) swap(point[i].y,point[i].z); }
81         llg ans=(llg)1e16;
82         for (llg i=0;i<(1<<G);i++) 
83             ans=min(work(i),ans);
84         printf("%lld\n",ans);
85     }
86     return 0;
87 }

 

posted @ 2017-02-23 19:00  №〓→龙光←  阅读(170)  评论(0编辑  收藏  举报