题意:
农夫为他的 N (1 ≤ N ≤ 100) 牛准备了 F (1 ≤ F ≤ 100)种食物和 D (1 ≤ D ≤ 100) 种饮料。每头牛都有各自喜欢的食物和饮料,而每种食物或饮料只能分配给一头牛。最多能有多少头牛可以同时得到喜欢的食物和饮料?
分析:
这个题的关键就是每个牛只能走一次,但是这头牛还连着饮料和食物,解决办法就是将牛拆分成两个点,一个点连着食物,一个点连着饮料,然后设置源点为0,汇点为n*2+x+y+1,跑一遍网络流板子就可以了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N = 1000,M = N*N;
const int inf = 0x3f3f3f3f;
int h[N],e[M],w[M],ne[M],idx;
int dis[N];
int n,x,y;
bool bfs(){
memset(dis,-1,sizeof dis);
dis[0] = 0;
queue<int> q;
q.push(0);
while(!q.empty()){
int t = q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i]){
int j = e[i];
if(dis[j] == -1 && w[i] != 0){
dis[j] = dis[t] + 1;
q.push(j);
}
}
}
return dis[n*2+x+y+1] != -1;
}
int dfs(int u,int flo){
if(u == n*2+x+y+1){
return flo;
}
int delta = flo;
for(int i=h[u];i!=-1;i=ne[i]){
int j = e[i] ;
if(dis[j] == dis[u] + 1 && w[i] > 0){
int x = min(delta,w[i]);
int d = dfs(j,x);
w[i] -= d;
w[i^1] += d;
delta -= d;
if(delta == 0) break;
}
}
return flo - delta;
}
void add(int a,int b,int c){
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx++;
}
signed main(){
cin>>n>>x>>y;
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++){
int f,d;
cin>>f>>d;
for(int j=1;j<=f;j++){
int t;
cin>>t;
add(n*2+t,i,1);
add(i,n*2+t,0);
}
add(i,n+i,1);
add(n+i,i,0);
for(int j=1;j<=d;j++){
int t;
cin>>t;
add(n+i,n*2+x+t,1);
add(n*2+x+t,n+i,0);
}
}
for(int i=1;i<=x;i++) add(0,n*2+i,1),add(n*2+i,0,0);
for(int i=1;i<=y;i++) add(n*2+x+y+1,n*2+x+i,0),add(n*2+x+i,n*2+x+y+1,1);
int ans = 0;
while(bfs()){
ans += dfs(0,inf);
}
cout<<ans<<endl;
return 0;
}