[HNOI2013] disinfection (D bipartite graph matching)

[HNOI2013] disinfection (luogu)

Title Description

 

Small T recently working in biological laboratories in big trouble.

Due to the recent upgrade of the laboratory, he ruled the cuvette is a cuboid with dimensions a * b * c, a, b, c are positive integers.

For convenience of the experiment, it was divided a * b * c cubes unit area, per unit cube size is 1 * 1 * 1.

Identified by (i, j, k) a unit cube, 1 <= i <= a, 1 <= j <= b, 1 <= k <= c.

The cuvette has no use for a long time, and now, T is small claim wherein some of the unit cubes tutor disinfecting operation region (each region may be repeated disinfection).

And because of the strict test requirements, he is required to use a specific reagent F to be disinfected.

Such agents particularly strange F, each time the size is x * y * z rectangular region (which consists of x * y * z units cubes) for disinfection,

Only need to use reagent F min {x, y, z} units. F expensive reagents, which can be a difficult task for small T.

Now you tell him, F reagent how many units of the least use. (Note: min {x, y, z} represents the minimum of x, y, z in.)

 

Input Format

 

The first line is a positive integer D, represents the number of data sets. Next, the data D is set, at the beginning of each set of three data number a, b, c indicates the size of the cuvette.

Next, there will be a matrix of 01 columns b-c rows separated by a space, 0 indicates that the corresponding unit does not require disinfection cube, 1 indicates that the corresponding unit cubes need to be disinfected;

For example, if a first line 201 as a third matrix, said unit cube (1,2,3) to be disinfected.

Input guaranteed a * b * c <= 5000, T <= 3.

 

Output Format

D contains only lines, each an integer representing the number corresponding to the cuvette reagent unit F minimum use.

 

Solution

There is a greedy strategy obvious: each disinfection order x, y, z 1 a is the other is the maximum

FIG third match will not (I may be too a konjac), found a, b, c there must be a <= 5000 1/3 ~ = 17.1,2 17 complexity can also be accepted.

You can then rotate the box, so that a, b, c a smallest rectangular high, it may wish to set a.

All units located at the same height as the cube layer, each layer is an enumeration of all this layer sterilization or stay

Stay compressed onto a plane, then that is a two-dimensional problem.

 

Digression:

In addition to matching of bipartite graph "0 element" and "element 1", the cover there is a minimum point "element 2":

Each side has two end points, both of selecting at least one

 

The number of each row requiring sterilization unit square on the plane and even columns edges, for the Minimum Vertex Cover

 

Code

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=5e3+10;
int match[N],head[N],nxt[N],tot,ver[N];
int T,a,b,c,n,ans,pos,s[3][N],cnt,vis[N];
bool flag[N];
void add(int x,int y)
{
    ver[++tot]=y,nxt[tot]=head[x],head[x]=tot;
}
bool dfs(int x)
{
    for(int i=head[x],y;i;i=nxt[i])
        if(vis[y=ver[i]]!=cnt)
        {
            vis[y]=cnt;
            if(!match[y] || dfs(match[y]))
            {
                match[y]=x;
                return 1;
            }
        }
    return 0;
}
void clear()
{
    tot=0;
    memset(head,0,sizeof(head));
    memset(match,0,sizeof(match));
}
int solve(int x)
{
    clear();
    int now=0;
    for(int i=0;i<a;i++)
        if(x&(1<<i)) flag[i+1]=false,now++;
        else flag[i+1]=true;
    for(int i=1;i<=n;i++)
        if(flag[s[0][i]]) add(s[1][i],s[2][i]);
    for(int i=1;i<=b;i++)
    {
        cnt++;
        if(dfs(i)) now++;
    }
    return now;
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        n=cnt=0,ans=1<<30;
        memset(vis,0,sizeof(vis));
        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;k<=c;k++)
                {
                    scanf("%d",&pos);
                    if(!pos) continue;
                    s[0][++n]=i,s[1][n]=j,s[2][n]=k;
                }
        int mi=min(a,min(c,b));
        if(mi==b) swap(a,b),swap(s[0],s[1]);
        if(mi==c) swap(a,c),swap(s[0],s[2]);
        for(int i=0;i<(1<<a);i++)
            ans=min(ans,solve(i));
        printf("%d\n",ans);
    }
    return 0;
}

 

 

 

Guess you like

Origin www.cnblogs.com/hsez-cyx/p/12348658.html