POJ2009 Moo University - Emergency Pizza Order 二分匹配

一边匹配一边加点,先加点,如果不能加了就用匈牙利调整。

有几个剪枝,就是<k的牛不用管了,然后记住吃不到的牛,下次包含于这个搭配的其他牛也一定失败。


Moo University - Emergency Pizza Order
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 1279 Accepted: 311

Description

Moo U's cafeteria has run out of hay and so must order pizzas for the C (1 <= C <= 1,000) calves attending Moo U. Conveniently, a large pizza from the local pizzeria, Pizza Farm, serves exactly one calf. 

Pizza Farm is willing to make a pizza for each calf, but, due to the size of the order, has three constraints on the order: 
* Although Pizza Farm has long list of T (1 <= T <= 30) vegetarian toppings, each of the pizzas must have exactly K (1 <= K <=T) toppings 
* No topping on a pizza can be duplicated (a pizza cannot have onions and onions, for example). 
* No two pizzas in the order can have the same set of toppings.For example, if pizza 1 has onions, green peppers, pineapples, and wheat grass, then it can be the only pizza with that exact set of toppings, although pizza 2 might have onions, green peppers, pineapples, and also olives.For ordering purposes, the toppings are numbered 1..T. 

The calves at Moo U are very picky when it comes to their pizza toppings. Some calves might not like all of the toppings available. 
A calf will eat a pizza only she likes every single one of the toppings on that pizza. Determine the maximum number of calves that can be fed. 

Input

* Line 1: Three integers: C, T, and K. 

* Lines 2..C+1: Each line of space-separated integers describes which toppings one of the calves likes. The first integer on a line is the number of topping the calf likes. The remaining integers on the line are the toppings that the calf likes. 

Output

* Line 1: A single integer, the maximum number of calves that can be fed. 

Sample Input

3 2 1
2 2 1
1 1
1 2

Sample Output

2

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>

using namespace std;

#define MAXN 111117
int dfs(int u);
int hash[MAXN];
int c,t,k;
int ans;
int cy[MAXN],mk[MAXN];
int cnts[1100],cw[1100][40],piz[1100];

int query(int k)
{
    int p;
    p=k%MAXN;
    while(hash[p]!=-1 && hash[p]!=k) p=(p+10)%MAXN;
    return p;
}

bool hashit(int k)
{
    int p;
    p=k%MAXN;
    while(hash[p]!=-1 && hash[p]!=k) p=(p+10)%MAXN;
    if(hash[p]==-1) hash[p]=k;
    else return false;
    return true;
}

int fail[MAXN],tp;

int coordinate(int u,int cnt,int id,int pz)
{
     if (cnts[u]-id+cnt<k) return 0;
     if(cnt==k)
     {
         int p=query(pz);
         if(mk[p]!=-1) return 0;
         int x=cy[p];
         mk[p]=1;
         if(dfs(x))
         {
             cy[p]=u;
             return 1;
         }
         return 0;
     }
     else
     {
        if(coordinate(u,cnt,id+1,pz)) return 1;
        else
        {
            pz|=(1<<(cw[u][id]-1));
            if(coordinate(u,cnt+1,id+1,pz)) return 1;
            return 0;
        }
     }
     return 0;

}

int newPiz(int u,int cnt,int id,int pz)
{
    if (cnts[u]-id+cnt<k) return 0;
    if(cnt==k)
    {
        if(!hashit(pz)) return 0;
        int p=query(pz);
        cy[p]=u;
        return 1;
    }
    else
    {
        if(newPiz(u,cnt,id+1,pz)) return 1;
        else
        {
            pz|=(1<<(cw[u][id]-1));
            if(newPiz(u,cnt+1,id+1,pz)) return 1;
            return 0;
        }
    }
    return 0;
}

int dfs(int u)
{
    if(cnts[u]<k) return 0;
    for(int i=0;i<tp;i++) if((piz[u]&(~fail[i]))==0) return 0;
    if(newPiz(u,0,0,0)) return 1;
    else if(coordinate(u,0,0,0)) return 1;
    else fail[tp++]=piz[u];
    return 0;
}

int main()
{
    while(~scanf("%d%d%d",&c,&t,&k))
    {
        for(int i=1;i<=c;i++)
        {
            piz[i]=0;
            scanf("%d",&cnts[i]);
            for(int j=0;j<cnts[i];j++)
            {
                scanf("%d",&cw[i][j]);
                piz[i]|=(1<<(cw[i][j]-1));
            }
        }
        tp=0;ans=0;
        memset(hash,-1,sizeof(hash));
        memset(cy,-1,sizeof(cy));
        for(int i=1;i<=c;i++)
        {
            memset(mk,-1,sizeof(mk));
            if(dfs(i)) ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值