题目描述
农夫约翰上个星期刚刚建好了他的新牛棚,他使用了最新的挤奶技术。不幸的是,由于工程问题,每个牛栏都不一样。第一个星期,农夫约翰随便地让奶牛们进入牛栏,但是问题很快地显露出来:每头奶牛都只愿意在她们喜欢的那些牛栏中产奶。上个星期,农夫约翰刚刚收集到了奶牛们的爱好的信息(每头奶牛喜欢在哪些牛栏产奶)。一个牛栏只能容纳一头奶牛,当然,一头奶牛只能在一个牛栏中产奶。
给出奶牛们的爱好的信息,计算最大分配方案。
输入输出格式
输入格式:
第一行 两个整数,N (0 <= N <= 200) 和 M (0 <= M <= 200) 。N 是农夫约翰的奶牛数量,M 是新牛棚的牛栏数量。
第二行到第N+1行 一共 N 行,每行对应一只奶牛。第一个数字 (Si) 是这头奶牛愿意在其中产奶的牛栏的数目 (0 <= Si <= M)。后面的 Si 个数表示这些牛栏的编号。牛栏的编号限定在区间 (1..M) 中,在同一行,一个牛栏不会被列出两次。
输出格式:
只有一行。输出一个整数,表示最多能分配到的牛栏的数量.
输入输出样例
说明
N (0 <= N <= 200)
M (0 <= M <= 200)
发现一道网络流水题(模板)。
设源点S=0,汇点T=n+m+1。
从S向每头牛建一条流量为1的边。
从每头牛向它们喜欢的牛栏建一条流量为1的边。
从牛栏向T建一条流量为1的边。
然后跑最大流就可以了。
(*^▽^*)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<string> 6 #define ll long long 7 #define DB double 8 #include<queue> 9 #define inf 2147480000 10 using namespace std; 11 inline int read() 12 { 13 int x=0,w=1;char ch=getchar(); 14 while(!isdigit(ch)){if(ch==‘-‘) w=-1;ch=getchar();} 15 while(isdigit(ch))x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar(); 16 return x*w; 17 } 18 const int N=1e6+90; 19 struct node{ 20 int u,v,ne,fl; 21 }e[N]; 22 int h[N],tot,n,m,S,T; 23 void add1(int u,int v,int fl) 24 { 25 tot++;e[tot]=(node){u,v,h[u],fl};h[u]=tot; 26 } 27 void add(int u,int v,int fl) 28 { 29 add1(u,v,fl);add1(v,u,0); 30 } 31 queue<int>q; 32 int d[N],ff; 33 bool bfs() 34 { 35 for(int i=S;i<=T;++i) d[i]=0; 36 d[S]=1;q.push(S); 37 while(!q.empty()) 38 { 39 ff=q.front();q.pop(); 40 for(int i=h[ff];i;i=e[i].ne) 41 { 42 int rr=e[i].v; 43 if(!d[rr] && e[i].fl) 44 d[rr]=d[ff]+1,q.push(rr); 45 } 46 } 47 return d[T]; 48 } 49 int dfs(int u,int fl) 50 { 51 if(u==T || fl==0) return fl; 52 int get=0,f; 53 for(int i=h[u];i;i=e[i].ne) 54 { 55 int rr=e[i].v; 56 if(d[rr]==d[u]+1 && e[i].fl) 57 { 58 f=dfs(rr,min(fl,e[i].fl)); 59 if(f==0) continue; 60 get+=f;fl-=f; 61 e[i].fl-=f;e[i^1].fl+=f; 62 if(fl==0) break; 63 } 64 } 65 if(get==0) d[u]=0; 66 return get; 67 } 68 int flow() 69 { 70 int ans=0; 71 while(bfs()) ans+=dfs(S,inf); 72 return ans; 73 } 74 int main() 75 { 76 n=read();m=read();tot=1; 77 S=0;T=n+m+1; 78 for(int i=1;i<=n;++i) add(S,i,1); 79 for(int i=n+1;i<=n+m;++i) add(i,T,1); 80 for(int i=1,si;i<=n;++i) 81 { 82 si=read(); 83 for(int j=1,k;j<=si;++j) 84 k=read(),add(i,k+n,1); 85 } 86 cout<<flow(); 87 return 0; 88 }