题目大意:有F种食物,D种饮料
N头奶牛,只能吃某种食物和饮料(而且只能吃特定的一份)
一种食物被一头牛吃了之后,其余牛就不能吃了
第一行有N,F,D三个整数
接着2-N+1行代表第i头牛,前面两个整数是Fi与Di(食物与饮料的种类数量),接着是食物的种类与饮料的种类
要求输出最多分配能够满足的牛的数量
题解:S-->food-->cow-->cow'-->drink-->T
切记要将牛拆点,因为每头牛只能喝一种饮料,吃一种食物。
#include<cstdio> #include<cmath> #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<queue> using namespace std; const int maxn=410,maxm=61000,inf=0x7fffffff; int n,f,d,a,b,c,s,t,tot=1,maxflow,head[maxn],cur[maxn],h[maxn]; queue<int> q; struct node{ int go,next,v; }e[maxm]; inline int read(){ int x=0;char ch=getchar(); while (ch>'9' || ch<'0') ch=getchar(); while (ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } inline void addedge(int x,int y,int v){ e[++tot]=(node){y,head[x],v};head[x]=tot; e[++tot]=(node){x,head[y],0};head[y]=tot; } bool bfs(){ for (int i=1;i<=t;i++) h[i]=-1; q.push(s);h[s]=0; while (!q.empty()){ int x=q.front();q.pop(); for (int i=head[x];i;i=e[i].next){ if (e[i].v&&h[e[i].go]==-1){ h[e[i].go]=h[x]+1; q.push(e[i].go); } } } return h[t]!=-1; } int dfs(int x,int f){ if (x==t) return f; int tmp,used=0; for (int i=cur[x];i;i=e[i].next){ if (e[i].v&&h[e[i].go]==h[x]+1){ tmp=dfs(e[i].go,min(e[i].v,f-used)); e[i].v-=tmp;if (e[i].v) cur[x]=i; e[i^1].v+=tmp;used+=tmp; if (used==f) return f; } } if (used==0) h[x]=-1; return used; } void dinic(){ maxflow=0; while (bfs()){ for (int i=1;i<=t;i++) cur[i]=head[i]; maxflow+=dfs(s,inf); } } int main(){ n=read();f=read();d=read(); s=n+n+f+d+1;t=s+1; for (int i=1;i<=f;i++) addedge(s,i+n+n,1); for (int i=1;i<=d;i++) addedge(n+n+f+i,t,1); for (int i=1;i<=n;i++) addedge(i,i+n,1); for (int i=1;i<=n;i++){ a=read();b=read(); for (int j=1;j<=a;j++){ c=read(); addedge(n+n+c,i,1); } for (int j=1;j<=b;j++){ c=read(); addedge(i+n,n+n+f+c,1); } } dinic(); printf("%d\n",maxflow); return 0; }