有 n 头牛,f 个食物,d 个饮料。n 头牛,每头牛都有一定的喜好,只喜欢几个食物和饮料。每个食物和饮料只能给一头牛。一头牛只能得到一个食物和饮料。而且一头牛必须同时获得一个食物和一个饮料才能满足,问至多有多少头牛可以获得满足
把食物和饮料放在两端,一头牛拆成两个点,两点之间容量为 1,喜欢的食物和饮料跟牛建条边,容量为 1,加个源点和汇点,源点与食物,饮料,汇点的边的容量都是 1,表示每种食物和饮料只有一个
#include<cstdio> #include<queue> #include<algorithm> #include<cstring> using namespace std; const int maxn=1014; const int inf=1e9; int g[maxn][maxn]; int pre[maxn]; int flow[maxn]; int maxflow; int N; queue<int> q; void init () { while (!q.empty()) q.pop(); fill(pre,pre+maxn,0); fill(flow,flow+maxn,0); maxflow=0; for (int i=0;i<maxn;i++) for (int j=0;j<maxn;j++) g[i][j]=0; } int bfs (int s,int t) { while (!q.empty()) q.pop(); for (int i=0;i<=N;i++) pre[i]=-1; pre[s]=0; q.push(s); flow[s]=inf; while (!q.empty()) { int x=q.front(); q.pop(); if (x==t) break; for (int i=0;i<=N;i++) { if (g[x][i]!=0&&pre[i]==-1) { pre[i]=x; flow[i]=min(flow[x],g[x][i]); q.push(i); } } } if (pre[t]==-1) return -1; else return flow[t]; } void Edmonds_Karp (int s,int t) { int increase=0; while ((increase=bfs(s,t))!=-1) { int k=t; while (k!=s) { int last=pre[k]; g[last][k]-=increase; g[k][last]+=increase; k=last; } maxflow+=increase; } } int main () { int n,f,d; while (~scanf("%d %d %d",&n,&f,&d)) { init (); N=f+d+2*n+1; for (int i=1;i<=f;i++) g[0][i]=1; for (int i=f+2*n+1;i<=f+2*n+d;i++) g[i][N]=1; for (int i=1;i<=n;i++) g[f+2*i-1][f+2*i]=1; int k1,k2,u; for (int i=1;i<=n;i++) { scanf ("%d %d",&k1,&k2); while (k1--) { scanf ("%d",&u); g[u][f+2*i-1]=1; } while (k2--) { scanf ("%d",&u); g[f+2*i][f+2*n+u]=1; } } Edmonds_Karp (0,N); printf ("%d ",maxflow); } return 0; }