给出n个人喜欢的饮料种类以及食物种类,每个人只能取其中一种且数量为1,现在给出有f中食物以及d种饮料,以及他们各自的数量,问如何安、排食物以及饮料,使得最多的人得到一个食物以及一瓶饮料
题目类似poj3281 dining 只是那题目每个种类都只有数量1 ,所以这道题目就只用才起点建边和终点建边的时候加上流量限制就可以了
首先,我们为了控制一个人只连一瓶饮料,一份食物,那么我们可以把一个人拆成两个,他们之间连一条权值为1的边,另外左边连它喜欢的食物,权值为1,右边连它喜欢的饮料,权值为1,在起点连食物的时候加流量限制,终点加流量限制,跑一遍最大流即可。
#include<iostream> #include<stdio.h> #include<memory.h> #include<cmath> using namespace std; #define MAXN 10005 #define MAXE 200000 #define INF 1e9 int ne,nv,tmp,s,t,index; struct Edge{ int next,pair; int v,cap,fLow; }edge[MAXE]; int net[MAXN]; int ISAP() { int numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN]; int cur_fLow,max_fLow,u,tmp,neck,i; memset(dist,0,sizeof(dist)); memset(numb,0,sizeof(numb)); memset(pre,-1,sizeof(pre)); for(i = 1 ; i <= nv ; ++i) curedge[i] = net[i]; numb[nv] = nv; max_fLow = 0; u = s; while(dist[s] < nv) { if(u == t) { cur_fLow = INF; for(i = s; i != t;i = edge[curedge[i]].v) { if(cur_fLow > edge[curedge[i]].cap) { neck = i; cur_fLow = edge[curedge[i]].cap; } } for(i = s; i != t; i = edge[curedge[i]].v) { tmp = curedge[i]; edge[tmp].cap -= cur_fLow; edge[tmp].fLow += cur_fLow; tmp = edge[tmp].pair; edge[tmp].cap += cur_fLow; edge[tmp].fLow -= cur_fLow; } max_fLow += cur_fLow; u = neck; } for(i = curedge[u]; i != -1; i = edge[i].next) if(edge[i].cap > 0 && dist[u] == dist[edge[i].v]+1) break; if(i != -1) { curedge[u] = i; pre[edge[i].v] = u; u = edge[i].v; }else{ if(0 == --numb[dist[u]]) break; curedge[u] = net[u]; for(tmp = nv,i = net[u]; i != -1; i = edge[i].next) if(edge[i].cap > 0) tmp = tmp<dist[edge[i].v]?tmp:dist[edge[i].v]; dist[u] = tmp + 1; ++numb[dist[u]]; if(u != s) u = pre[u]; } } return max_fLow; } void addedge(int u,int v,int f) { edge[index].next = net[u]; edge[index].v = v; edge[index].cap = f; edge[index].fLow = 0; edge[index].pair = index+1; net[u] = index++; edge[index].next = net[v]; edge[index].v = u; edge[index].cap = 0; edge[index].fLow = 0; edge[index].pair = index-1; net[v] = index++; } int main() { int i,j,n,f,d; while(scanf("%d%d%d",&n,&f,&d)!=EOF) { int conte=0; index=1; s = f+n+n+d+1; t = s+1; nv=t; memset(net,-1,sizeof(net)); for(i=1;i<=f;i++) { int temp; scanf("%d",&temp); addedge(s,i,temp); } for(i=1;i<=d;i++) { int temp; scanf("%d",&temp); addedge(f+2*n+i,t,temp); } for(i=1;i<=n;i++) { addedge(f+i,f+n+i,1); char ts[3000]; int tc=0; scanf("%s",ts); for(j=0;ts[j];j++) { if(ts[j]=='Y') { addedge(j+1,f+i,1); } } /*if(tc==f) addedge(s,f+i,1);*/ } for(i=1;i<=n;i++) { //addedge(f+n+i,t,1); char ts[3000]; int tc=0; scanf("%s",ts); for(j=0;ts[j];j++) { if(ts[j]=='Y') { addedge(f+n+i,f+2*n+j+1,1); } } /*if(tc==d) addedge(f+n+i,t,1);*/ } int ans=ISAP(); printf("%d\n",ans); } return 0; }