N头牛,D种饮料,F种食物,每天牛吃一种食物一种饮料,食物和饮料都只有一份。问最大满足多少头牛。
构图:由于每头牛只需一份饮料和食物,所以每头牛要拆为两点,连容量为1的边。起点到所有食物连容量为1的边,饮料到汇点连容量为1的边。牛再和食物,饮料连。
构图的时候仔细一点就好了。。
#include<cstdio>
#include <iostream>
#include<cstring>
#include<algorithm>
#define N 5005
#define M 100005 //这个要够大。。
#define inf 999999999
using namespace std;
int s,t,num,adj[N],dis[N],q[N];
struct edge
{
int v,w,pre;
}e[M];
int min(int g,int h)
{
if(g>h)
return h;
else
return g;
}
void insert(int u,int v,int w) //上面的insert可以写成下面这种。。
{
e[num].v=v;
e[num].w=w;
e[num].pre=adj[u];
adj[u]=num++;
e[num].v=u;
e[num].w=0;
e[num].pre=adj[v];
adj[v]=num++;
}
int bfs()
{
int i,x,v,tail=0,head=0;
memset(dis,0,sizeof(dis));
dis[s]=1;
q[tail++]=s;
while(head<tail)
{
x=q[head++];
for(i=adj[x];i!=-1;i=e[i].pre)
if(e[i].w&&dis[v=e[i].v]==0)
{
dis[v]=dis[x]+1;
if(v==t)
return 1;
q[tail++]=v;
}
}
return 0;
}
int dfs(int s,int limit)
{
if(s==t)
return limit;
int i,v,tmp,cost=0;
for(i=adj[s];i!=-1;i=e[i].pre)
if(e[i].w&&dis[s]==dis[v=e[i].v]-1)
{
tmp=dfs(v,min(limit-cost,e[i].w));
if(tmp>0)
{
e[i].w-=tmp;
e[i^1].w+=tmp;
cost+=tmp;
if(limit==cost)
break;
}
else dis[v]=-1;
}
return cost;
}
int Dinic()
{
int ans=0;
while(bfs())
ans+=dfs(s,inf);
return ans;
}
int main ()
{
int Num,F,D;
int i,j,fj,dj,f,d;
while(scanf("%d%d%d",&Num,&F,&D)!=EOF)
{
memset(adj,-1,sizeof(adj));
num=0;
for(i=1;i<=F;i++)
insert(0,i,1);
for(i=F+2*Num+1;i<=F+2*Num+D;i++)
insert(i,F+D+2*Num+1,1);
for(i=F+1;i<=F+Num;i++)
insert(i,i+Num,1);
for(i=1;i<=Num;i++)
{
cin>>f>>d;
for(j=1;j<=f;j++)
{
cin>>fj;
insert(fj,i+F,1);
}
for(j=1;j<=d;j++)
{
cin>>dj;
insert(F+Num+i,F+2*Num+dj,1);
}
}
s=0;
t=F+D+2*Num+1;
printf("%d\n",Dinic());
}
return 0;
}