题目大意:有m个猪圈,每个猪圈都有锁,有n个顾客,每个顾客都有某几个猪圈的钥匙,顾客按先后顺序来,并且每个顾客购买量有一个上限bi,当一个顾客来了后打开一些猪圈,这些猪圈里的猪可以来回调整,问最多能卖出多少猪。
网络流问题难在建模,还需多做题多接触建模的方法。
将顾客看做节点,引入源汇两点,每个顾客节点与汇点连接一条容量为bi的边,表示购买上限,每个猪圈的第一个打开的顾客节点与源点连接一条容量为该猪圈猪的总数的边,每个猪圈之后再来的人则与第一个顾客连接一条容量为正无穷的边,因为第一个顾客来了后可以调整数量,然后求最大流即可。
#include <stdio.h> #include <string.h> #define INF 3000000 int s,t; int customer[110][110],flow[110][110]; int i,j; void init() { int m,n; int num,k; int house[1010],last[1010]; memset(last,0,sizeof(last)); memset(customer,0,sizeof(customer)); scanf("%d%d",&m,&n); s=0;t=n+1; for(i=1;i<=m;i++) scanf("%d",&house[i]); for(i=1;i<=n;i++) { scanf("%d",&num); for(j=0;j<num;j++) { scanf("%d",&k); if(last[k]==0) customer[s][i]=customer[s][i]+house[k]; else customer[last[k]][i]=INF; last[k]=i; } scanf("%d",&customer[i][t]); } } void ford() { int prev[110],minflow[110]; int queue[110]; int qs,qe,v,p; for(i=0;i<110;i++) for(j=0;j<110;j++) flow[i][j]=0; minflow[0]=INF; while(1) { for(i=0;i<110;i++) prev[i]=-2; prev[0]=-1; qs=0;queue[qs]=0;qe=1; while(qs<qe&&prev[t]==-2) { v=queue[qs];qs++; for(i=0;i<t+1;i++) { if(prev[i]==-2&&(p=customer[v][i]-flow[v][i])) { prev[i]=v;queue[qe]=i;qe++; minflow[i]=(minflow[v]<p) ? minflow[v]:p; } } } if(prev[t]==-2) break; for(i=prev[t],j=t;i!=-1;j=i,i=prev[i]) { flow[i][j]=flow[i][j]+minflow[t]; flow[j][i]=-flow[i][j]; } } for(i=0,p=0;i<t;i++) p+=flow[i][t]; printf("%d ",p); } int main() { init(); ford(); return 0; }