poj 3281 Dining
Dining
题目大意:
n头牛,f种食物,d种饮料, 每头牛有喜欢的食物、饮料, 每头牛只能分配一种食物和一种饮料 问最后最多能满足多少头牛
/* 每头牛只能选择一种食物和一种饮料,拆点可以进行容量限制 */ #include<iostream> #include<cstdio> #include<queue> #define maxn 501 using namespace std; int n,f,d,num=1,lev[maxn],head[maxn],cur[maxn],t,ans; struct node{ int to,pre,cap; }e[maxn*maxn*2]; void Insert(int from,int to,int v){ e[++num].to=to; e[num].cap=v; e[num].pre=head[from]; head[from]=num; } bool bfs(){ queue<int>q; for(int i=0;i<=t;i++)cur[i]=head[i],lev[i]=-1; q.push(0); lev[0]=0; while(!q.empty()){ int now=q.front();q.pop(); for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(lev[to]==-1&&e[i].cap>0){ lev[to]=lev[now]+1; q.push(to); if(to==t)return 1; } } } return 0; } int dinic(int now,int flow){ if(now==t)return flow; int rest=0,delta; for(int &i=cur[now];i;i=e[i].pre){ int to=e[i].to; if(lev[to]==lev[now]+1&&e[i].cap>0){ delta=dinic(to,min(e[i].cap,flow-rest)); if(delta){ e[i].cap-=delta;e[i^1].cap+=delta; rest+=delta; if(rest==flow)break; } } } if(rest!=flow)lev[now]=-1; return rest; } int main(){ freopen("Cola.txt","r",stdin); scanf("%d%d%d",&n,&f,&d); t=f+2*n+d+1; for(int i=1;i<=n;i++){ Insert(i+f,i+n+f,1); Insert(i+n+f,i+f,0); } for(int i=1;i<=f;i++){ Insert(0,i,1); Insert(i,0,0); } int a,b,x,y,z; for(int i=1;i<=n;i++){ scanf("%d%d",&a,&b); for(int j=1;j<=a;j++){//食物向牛连边 scanf("%d",&x); Insert(x,i+f,1); Insert(i+f,x,0); } for(int j=1;j<=b;j++){//牛向饮料连边 scanf("%d",&x); Insert(i+f+n,x+2*n+f,1); Insert(x+2*n+f,i+f+n,0); } } for(int i=1;i<=d;i++){//饮料向汇点连边 Insert(i+f+2*n,t,1); Insert(t,i+f+2*n,0); } while(bfs()) ans+=dinic(0,9999999); printf("%d",ans); }