【bzoj1711/Usaco2007 Open】Dining吃饭——网络流

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} 中选

Sample Output

3
 

 
听说是三分图啊???就是从源向食物连一条权值为1的边,从饮料向汇连一条权值为1的边,将一头牛x拆成两个点x和x',从该牛能吃的食物向x和x'向能喝的饮料连边,权值也为1。然后跑一遍最大流即可。
代码:
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 const int N=105,inf=0x3f3f3f3f;
 5 long long an=0;
 6 int n,D,F,T,tot=1,m=100;
 7 int cur[N*4],first[N*4],d[N*4],q[N*4];
 8 struct node{
 9     int ne,to,w;
10 }e[500500];
11 int read(){
12     int ans=0,f=1;char c=getchar();
13     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
14     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
15     return ans*f;
16 }
17 void ins(int u,int v,int w){
18     e[++tot]=(node){first[u],v,w};first[u]=tot;
19     e[++tot]=(node){first[v],u,0};first[v]=tot;
20 }
21 bool bfs(){
22     memset(d,-1,sizeof(d));d[0]=0;q[0]=0;
23     int h=0,t=1;
24     while(h!=t){
25         int x=q[h++];if(h>=400)h=0;
26         for(int i=first[x];i;i=e[i].ne){
27             int to=e[i].to;
28             if(d[to]==-1&&e[i].w>0){
29                 d[to]=d[x]+1;
30                 q[t++]=to;if(t>=400)t=0;
31             }
32         }
33     }
34     if(d[T]==-1)return 0;
35     return 1;
36 }
37 int dfs(int x,int a){
38     if(x==T||!a)return a;
39     int flow=0,f;
40     for(int &i=cur[x];i;i=e[i].ne){
41         int to=e[i].to;
42         if(d[to]==d[x]+1&&(f=dfs(to,std::min(e[i].w,a)))>0){
43             e[i].w-=f;
44             e[i^1].w+=f;
45             flow+=f;
46             a-=f;
47             if(!a)break;
48         }
49     }
50     return flow;
51 }
52 int main(){
53     n=read();F=read();D=read();
54     T=4*m+1;
55     for(int i=1;i<=F;i++)ins(0,2*m+i,1);
56     for(int i=1;i<=D;i++)ins(3*m+i,T,1);
57     for(int i=1;i<=n;i++)ins(i,i+m,1);
58     for(int i=1,d,f;i<=n;i++){
59         f=read();d=read();int a;
60         while(f--)a=read(),ins(2*m+a,i,1);    
61         while(d--)a=read(),ins(m+i,3*m+a,1);
62     }
63     while(bfs()){
64         for(int i=0;i<=T;i++)cur[i]=first[i];
65         an+=dfs(0,inf);
66     }
67     printf("%lld",an);
68     return 0;
69 }
bzoj1711
原文地址:https://www.cnblogs.com/JKAI/p/7536813.html