题目链接:
思路:为了控制一个人只连一瓶饮料,一份食物,那么我们可以把一个人拆成两个,他们之间连一条权值为1的边,另外左边连它喜欢的食物,权值为1,右边连它喜欢的饮料,权值为1,在起点连食物的时候加流量限制,终点加流量限制,跑一遍最大流即可。
View Code
1 #include2 #include 3 #include 4 using namespace std; 5 #define MAXN 1111 6 #define MAXM 88888888 7 struct Edge{ 8 int v,cap,next; 9 }edge[MAXM]; 10 11 int head[MAXN]; 12 int pre[MAXN]; 13 int cur[MAXN]; 14 int level[MAXN]; 15 int gap[MAXN]; 16 int NE,NV,vs,vt,n,f,d; 17 int Food[MAXN]; 18 int Drink[MAXN]; 19 20 21 void Insert(int u,int v,int cap,int cc=0){ 22 edge[NE].v=v;edge[NE].cap=cap; 23 edge[NE].next=head[u];head[u]=NE++; 24 25 edge[NE].v=u;edge[NE].cap=cc; 26 edge[NE].next=head[v];head[v]=NE++; 27 } 28 29 30 31 int SAP(int vs,int vt){ 32 memset(pre,-1,sizeof(pre)); 33 memset(level,0,sizeof(level)); 34 memset(gap,0,sizeof(gap)); 35 for(int i=0;i level[v]){ 61 cur[u]=i; 62 minlevel=level[v]; 63 } 64 } 65 gap[level[u]]--; 66 if(gap[level[u]]==0)break; 67 level[u]=minlevel+1; 68 gap[level[u]]++; 69 u=pre[u]; 70 } 71 return maxflow; 72 } 73 74 int main(){ 75 char str[MAXN]; 76 while(~scanf("%d%d%d",&n,&f,&d)){ 77 vs=0,vt=f+2*n+d+1,NV=vt+1,NE=0; 78 memset(head,-1,sizeof(head)); 79 for(int i=1;i<=f;i++){ 80 scanf("%d",&Food[i]); 81 Insert(vs,i,Food[i]);//源点与每一种食物连容量为food[i]的边。 82 } 83 for(int i=1;i<=d;i++){ 84 scanf("%d",&Drink[i]); 85 Insert(i+2*n+f,vt,Drink[i]);//每种饮料与汇点连容量为Drink[i]的边。 86 } 87 for(int i=1;i<=n;i++){ 88 Insert(i+f,i+f+n,1);//将人拆点,人与人之间连容量为1的边 89 } 90 for(int i=1;i<=n;i++){ 91 scanf("%s",str+1); 92 for(int j=1;j<=f;j++){ 93 if(str[j]=='Y'){ 94 Insert(j,i+f,1);//食物与人连边。 95 } 96 } 97 } 98 for(int i=1;i<=n;i++){ 99 scanf("%s",str+1);100 for(int j=1;j<=d;j++){101 if(str[j]=='Y'){102 Insert(i+f+n,f+2*n+j,1);//人与饮料之间连容量为1的边103 }104 }105 }106 printf("%d\n",SAP(vs,vt));107 }108 return 0;109 }