[USACO 4.2] 完美的牛栏

★★☆   输入文件:stall4.in   输出文件:stall4.out   简单对比
时间限制:1 s   内存限制:128 MB

USACO/stall4(译by Felicia Crazy)

描述


农夫约翰上个星期刚刚建好了他的新牛棚,他使用了最新的挤奶技术。不幸的是,由于工程问题,每个牛栏都不一样。第一个星期,农夫约翰随便地让奶牛们进入牛栏,但是问题很快地显露出来:每头奶牛都只愿意在她们喜欢的那些牛栏中产奶。上个星期,农夫约翰刚刚收集到了奶牛们的爱好的信息(每头奶牛喜欢在哪些牛栏产奶)。一个牛栏只能容纳一头奶牛,当然,一头奶牛只能在一个牛栏中产奶。

给出奶牛们的爱好的信息,计算最大分配方案。


格式

PROGRAM NAME: stall4

INPUT FORMAT:

(file stall4.in)

 

第一行
两个整数,N (0 <= N <= 200)和M (0 <= M <= 200)。N是农夫约翰的奶牛数量,M是新牛棚的牛栏数量。
第二行到第N+1行

一共N行,每行对应一只奶牛。第一个数字(Si)是这头奶牛愿意在其中产奶的牛栏的数目(0 <= Si<= M)。后面的Si个数表示这些牛栏的编号。牛栏的编号限定在区间(1..M)中,在同一行,一个牛栏不会被列出两次。


OUTPUT FORMAT:

(file stall4.out)

 只有一行。输出一个整数,表示最多能分配到的牛栏的数量。

SAMPLE INPUT (file stall4.in)

5 5

2 2 5

3 2 3 4

2 1 5

3 1 2 5

1 2

SAMPLE OUTPUT (file stall4.out)

4

 思路

最大流

代码实现

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 const int maxn=1e5;
 5 inline int min_(int x,int y){return x<y?x:y;}
 6 int n,m,s,t,ans;
 7 int a,b;
 8 int h[maxn],hs=1,ew[maxn],et[maxn],en[maxn];
 9 void add(int u,int v){
10     ++hs,et[hs]=v,ew[hs]=1,en[hs]=h[u],h[u]=hs;
11     ++hs,et[hs]=u,ew[hs]=0,en[hs]=h[v],h[v]=hs;
12 }
13 int q[maxn],head,tail;
14 int d[maxn];
15 void SPFA(int s){
16     memset(d,0,sizeof(d));
17     head=tail=0;
18     q[head++]=s,d[s]=1;
19     while(head>tail){
20         a=q[tail++];
21         for(int i=h[a];i;i=en[i])
22         if(!d[et[i]]&&ew[i]){
23             d[et[i]]=d[a]+1;
24             if(et[i]==t) return;
25             q[head++]=et[i];
26         }
27     }
28 }
29 int ap(int k,int nw){
30     if(k==t) return nw;
31     int bw=nw;
32     for(int i=h[k];i;i=en[i])
33     if(ew[i]&&d[et[i]]==d[k]+1){
34         int dw=ap(et[i],min_(bw,ew[i]));
35         if(dw) ew[i]-=dw,ew[i^1]+=dw,bw-=dw;
36         else d[et[i]]=0;
37     }
38     return nw-bw;
39 }
40 void Dinic(){while(SPFA(s),d[t]) ans+=ap(s,n);}
41 int main(){
42     freopen("stall4.in","r",stdin);
43     freopen("stall4.out","w",stdout);
44     scanf("%d%d",&n,&m);
45     s=n+m+1,t=s+1;
46     for(int i=1;i<=n;i++) add(s,i);
47     for(int i=1;i<=m;i++) add(n+i,t);
48     for(int i=1;i<=n;i++){
49         scanf("%d",&a);
50         for(int j=1;j<=a;j++){
51             scanf("%d",&b);
52             add(i,n+b);
53         }
54     }
55     Dinic();
56     printf("%d\n",ans);
57     return 0;
58 }

 

posted @ 2017-06-17 20:07  J_william  阅读(325)  评论(0编辑  收藏  举报