题意:
农场主有f种食物,d种饮料,n头牛。
接下来的n行每行第一个数代表第i头牛喜欢吃的食物数量,和第i头牛喜欢喝的饮料数目。
接下来分别是喜欢的食物和饮料的编号。
求解:农场主最多能保证几头牛同时能吃到喜欢的食物和喜欢的饮料。
思路:
从源点到每种食物加流量为1的边,保证每种食物只能被吃一次。
将每头牛分为两个点,连一条流量为1的边,保证每头牛最多只能吃一份食物喝一份饮料。
将每种饮料和汇点都进行连接,同样流量为1。
将牛喜欢的食物和牛进行连边流量为1,将另一组代表牛的点和喜欢的饮料进行连边,同样流量为1。
建好图之后就变成了最大流问题了。
这里留一个用dinic解决最大流问题的模板。
/************************************************************************* > File Name: T.cpp > Author: ttpond > Created Time: 2015-8-22 12:4:42 ************************************************************************/ #include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<math.h> #include<vector> #include<map> #include<queue> #include<stack> #include<set> using namespace std; int z; int n,f,d; int pho[405][405]; int dis[410]; int nb; bool BFS() { nb++; int i,j; memset(dis,-1,sizeof(dis)); int tmp; queue<int>q; dis[1]=0; q.push(1); while(!q.empty()) { tmp=q.front(); q.pop(); for(int i=1; i<=z; i++) { if(dis[i]<0&&pho[tmp][i]) { dis[i]=dis[tmp]+1; q.push(i); } } } if(dis[z]>0) return 1; else return 0; } int findans(int x,int low) { int i,a=0; if(x==z) return low; for(i=1; i<=z; i++) { if(pho[x][i]>0&&dis[i]==dis[x]+1&&(a=findans(i,min(low,pho[x][i])))) { pho[x][i]-=a; pho[i][x]+=a; return a; } } return 0; } int main() { int a,b,tmp; scanf("%d%d%d",&n,&f,&d); z=2+f+n*2+d; memset(pho,0,sizeof(pho)); for(int i=2; i<=1+f; i++) { pho[1][i]=1; } for(int i=f+2; i<=f+n+1; i++) { pho[i][i+n]=1; } for(int i=2+f+n*2; i<=1+f+n*2+d; i++) { pho[i][2+f+n*2+d]=1; } for(int i=1; i<=n; i++) { scanf("%d%d",&a,&b); for(int j=1; j<=a; j++) { scanf("%d",&tmp); pho[tmp+1][i+f+1]=1; } for(int j=1; j<=b; j++) { scanf("%d",&tmp); pho[i+f+1+n][tmp+f+1+n*2]=1; } } int ans=0,tans; while(BFS()) { while(tans=findans(1,0x7fffffff)) { ans+=tans; } } printf("%d ",ans); }