题意:有F种食物,D种饮料,N头牛。每头牛只吃某种食物和饮料(都只吃一份)。每种食物和饮料都只有一份。给出每头牛吃的食物序号和饮料序号。求能够满足的牛的最大数量
思路:最大流。将牛拆点,防止一头牛吃多中食物或多种饮料。
#include <stdio.h>
#include <string.h>
#define N 405
int flow[N][N],cap[N][N],a[N],p[N],q[N];
int n,f,d;
int min(int a,int b){
if(a<b)
return a;
return b;
}
int maxflow(int s,int t){
int i,j,front,rear,res=0;
while(1){
memset(a,0,sizeof(a));
memset(p,0,sizeof(p));
a[s] = 0x3fffffff;
front = rear = -1;
q[++rear] = s;
while(front < rear){
i = q[++front];
for(j = 0;j<=t;j++){
if(!a[j] && cap[i][j]-flow[i][j]>0){
p[j] = i;
q[++rear] = j;
a[j] = min(a[i],cap[i][j]-flow[i][j]);
}
}
}
if(!a[t])
break;;
for(j = t;j!=0;j=p[j]){
flow[p[j]][j] += a[t];
flow[j][p[j]] -= a[t];
}
res += a[t];
}
return res;
}
int main(){
freopen("a.txt","r",stdin);
while(scanf("%d %d %d",&n,&f,&d)!=EOF){
int i,j,numf,numd;
memset(flow,0,sizeof(flow));
memset(cap,0,sizeof(cap));
for(i = 1;i<=n;i++){
scanf("%d %d",&numf,&numd);
while(numf--){
scanf("%d",&j);
cap[0][j] = 1;
cap[j][i+f] = 1;
}
while(numd--){
scanf("%d",&j);
cap[f+n+i][f+2*n+j] = 1;
cap[f+2*n+j][f+2*n+d+1] = 1;
}
cap[f+i][f+n+i] = 1;
}
printf("%d\n",maxflow(0,f+2*n+d+1));
}
return 0;
}