1711: [Usaco2007 Open]Dining吃饭
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1055 Solved: 567
[ Submit][ Status][ Discuss]
Description
农夫JOHN为牛们做了很好的食品,但是牛吃饭很挑食. 每一头牛只喜欢吃一些食品和饮料而别的一概不吃.虽然他不一定能把所有牛喂饱,他还是想让尽可能多的牛吃到他们喜欢的食品和饮料. 农夫JOHN做了F (1 <= F <= 100) 种食品并准备了D (1 <= D <= 100) 种饮料. 他的N (1 <= N <= 100)头牛都以决定了是否愿意吃某种食物和喝某种饮料. 农夫JOHN想给每一头牛一种食品和一种饮料,使得尽可能多的牛得到喜欢的食物和饮料. 每一件食物和饮料只能由一头牛来用. 例如如果食物2被一头牛吃掉了,没有别的牛能吃食物2.
Input
* 第一行: 三个数: N, F, 和 D
* 第2..N+1行: 每一行由两个数开始F_i 和 D_i, 分别是第i 头牛可以吃的食品数和可以喝的饮料数.下F_i个整数是第i头牛可以吃的食品号,再下面的D_i个整数是第i头牛可以喝的饮料号码.
Output
* 第一行: 一个整数,最多可以喂饱的牛数.
Sample Input
4 3 3
2 2 1 2 3 1
2 2 2 3 1 2
2 2 1 3 1 2
2 1 1 3 3
输入解释:
牛 1: 食品从 {1,2}, 饮料从 {1,2} 中选
牛 2: 食品从 {2,3}, 饮料从 {1,2} 中选
牛 3: 食品从 {1,3}, 饮料从 {1,2} 中选
牛 4: 食品从 {1,3}, 饮料从 {3} 中选
2 2 1 2 3 1
2 2 2 3 1 2
2 2 1 3 1 2
2 1 1 3 3
输入解释:
牛 1: 食品从 {1,2}, 饮料从 {1,2} 中选
牛 2: 食品从 {2,3}, 饮料从 {1,2} 中选
牛 3: 食品从 {1,3}, 饮料从 {1,2} 中选
牛 4: 食品从 {1,3}, 饮料从 {3} 中选
Sample Output
3
输出解释:
一个方案是:
Cow 1: 不吃
Cow 2: 食品 #2, 饮料 #2
Cow 3: 食品 #1, 饮料 #1
Cow 4: 食品 #3, 饮料 #3
用鸽笼定理可以推出没有更好的解 (一共只有3总食品和饮料).当然,别的数据会更难.
输出解释:
一个方案是:
Cow 1: 不吃
Cow 2: 食品 #2, 饮料 #2
Cow 3: 食品 #1, 饮料 #1
Cow 4: 食品 #3, 饮料 #3
用鸽笼定理可以推出没有更好的解 (一共只有3总食品和饮料).当然,别的数据会更难.
HINT
Source
看到这数据范围就想到网络流
好久没写了QAQ
板子都快忘了QAQ
主要是难在建图啦
刚开始没想出来
看了题解QAQ
传说中的三分图匹配2333
建图方式摘自hzwer博客:
#include<cstdio>
#include<algorithm>
#include<cstring>
const int inf=2*1e9,N=500,M=30000,len=3000;
int S,T;
struct node
{
int to,next,v;
}e[M*2];
int cnt=1;
int first[N],cur[N],dis[N],qu[len+5];
inline void insert(int u,int v,int q)
{
e[++cnt]=(node){v,first[u],q};first[u]=cnt;
e[++cnt]=(node){u,first[v],0};first[v]=cnt;
// printf("std:: %d %d %d\n",u,v,q);
}
bool bfs()
{
memset(dis,-1,sizeof(dis));
int head=1,tail=2;
qu[1]=S;dis[S]=0;
while(head!=tail)
{
int rr=qu[head++];if(head==len) head=0;
for(int k=first[rr];k;k=e[k].next)
if(dis[e[k].to]==-1&&e[k].v)
{
dis[e[k].to]=dis[rr]+1;
qu[tail++]=e[k].to;if(tail==len)tail=0;
}
}
return dis[T]==-1?0:1;
}
int dfs(int x,int a)
{
if(x==T||a==0) return a;
int flow=0;
for(int &k=cur[x];k;k=e[k].next)
if(e[k].v&&dis[e[k].to]==dis[x]+1)
{
int t=dfs(e[k].to,std::min(e[k].v,a));
e[k].v-=t,e[k^1].v+=t;
flow+=t,a-=t;
if(!a) break;
}
if(!flow) dis[x]=-1;
return flow;
}
int main()
{
int n,f,d,k,p,q;
scanf("%d %d %d",&n,&f,&d);
S=0;T=f+2*n+d+1;
for(int i=1;i<=f;i++) insert(S,i,1);
for(int i=1;i<=d;i++) insert(f+2*n+i,T,1);
for(int i=1;i<=n;i++) insert(f+i,f+n+i,1);
for(int i=1;i<=n;i++)
{
scanf("%d %d",&p,&q);
for(int j=1;j<=p;j++) scanf("%d",&k),insert(k,f+i,1);
for(int j=1;j<=q;j++) scanf("%d",&k),insert(f+n+i,f+2*n+k,1);
}
int ans=0;
while(bfs())
{
// printf("a");
for(int i=S;i<=T;i++) cur[i]=first[i];
ans+=dfs(S,inf);
}
printf("%d\n",ans);
return 0;
}