题意:
思路: 网络流 重在建图…建完了图 就一切都好说了
这道题 我的想法是 先把源点和所有的食品连上边 (容量为1)
再把食品和对应的奶牛连上边 (容量为1)
这个时候要拆点 因为每只奶牛只能才吃1种东西嘛
就把奶牛拆成两个点
两个点之间连上一条容量为1的边
把奶牛分裂的第二个点 连到对应的饮料上
最后所有饮料向汇点连一条容量为1的边就好啦
大功告成~~~
//By SiriusRen#include#include #include #include using namespace std;#define N 100050int n,f,d,ans,xx,w[N],v[N],first[555],tot,next[N],vis[N],yy,jy;void add(int x,int y,int z){ w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++;}bool tell(){ queue q; q.push(0); memset(vis,-1,sizeof(vis)); vis[0]=0; while(!q.empty()){ int t=q.front();q.pop(); for(int i=first[t];~i;i=next[i]){ if(w[i]&&vis[v[i]]==-1){ q.push(v[i]); vis[v[i]]=vis[t]+1; } } } return vis[501]!=-1;}int zeng(int x,int y){ if(x==501)return y; int r=0; for(int i=first[x];y>r&&~i;i=next[i]){ if(w[i]&&vis[v[i]]==vis[x]+1){ int t=zeng(v[i],min(y-r,w[i])); w[i]-=t,w[i^1]+=t,r+=t; } } if(!r)vis[x]=-1; return r;}void flow(){ while(tell())while(xx=zeng(0,0x3fffffff))ans+=xx; printf("%d\n",ans);}int main(){ memset(first,-1,sizeof(first)); scanf("%d%d%d",&n,&f,&d); for(int i=1;i<=f;i++)add(0,i,1),add(i,0,0); for(int i=1;i<=n;i++){ add(100+i,200+i,1); add(200+i,100+i,0); scanf("%d%d",&xx,&yy); for(int j=1;j<=xx;j++){ scanf("%d",&jy); add(jy,100+i,1); add(100+i,jy,0); } for(int j=1;j<=yy;j++){ scanf("%d",&jy); add(200+i,300+jy,1); add(300+jy,200+i,0); } } for(int i=1;i<=d;i++)add(300+i,501,1),add(501,300+i,0); flow();}