先翻译一下吧(题面可以在原OJ上找)
Mirko在一个由M个锁着的猪舍组成的养猪场工作,Mirko无法解锁任何猪舍,因为他没有钥匙。客户纷纷来到农场。他们每个人都有一些猪舍的钥匙,并想购买一定数量的猪。
有关计划在特定日期访问农场的客户的所有数据都可以在清晨获得Mirko,以便他可以制定销售计划以最大化销售的猪数量。
更准确地说,程序如下:顾客到达,打开他有钥匙的所有猪舍,Mirko将所有未开封的猪舍中的一定数量的猪卖给他,如果Mirko想要的话,他可以将剩余的猪重新分配到解锁的猪舍。
每个猪舍都可以放置无限数量的猪。顾客来的顺序不能改变,猪舍在顾客走后锁上。
编写一个程序,找出当天可以卖出的最大猪数。
解析
这确实是网络流建图好题。
首先,顾客来的顺序很重要,
因为当一个拥有猪舍X的钥匙的顾客i来后,
下一个拥有X的钥匙的顾客j实际上也能买到i能买到的猪(因为其他猪舍的猪可以在i买后调整到X中)。
因此,将j和i连边即可,流量为INF。
然后,若i是第一个打开X的人,就将i和汇点T连边,流量为X的初始猪数。
最后,将源点与每个顾客连边,流量为顾客最多买的猪,
再跑最大流就行了!
上AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; inline int read(){ int sum=0,f=1;char ch=getchar(); while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();} return f*sum; } const int INF=0x3f3f3f3f; struct node{ int next,to,w; }e[100001]; struct cus{ int ksum;/*钥匙数*/ int key[1001];/*钥匙*/ int sum;/*买猪的最大数*/ }c[101]; int n,m,s,t; int a[100001]; int head[100001],cnt=1; int d[100001],las[100001]/*i猪舍的上一个顾客*/; void add(int x,int y,int w){ // printf("from: %d to: %d ",x,y); e[++cnt].to=head[x]; e[cnt].next=y; e[cnt].w=w; head[x]=cnt; } bool bfs(){ queue <int> que; memset(d,0,sizeof(d)); que.push(s); d[s]=1; while(!que.empty()){ int x=que.front(); que.pop(); for(int i=head[x];i;i=e[i].to){ int k=e[i].next; if(!e[i].w||d[k]) continue; d[k]=d[x]+1; que.push(k); } } return d[t]; } int dfs(int x,int mi){ if(x==t||!mi) return mi; int ret=0,a=0; for(int i=head[x];i;i=e[i].to){ int k=e[i].next; if(!e[i].w||d[k]!=d[x]+1) continue; ret=dfs(k,min(mi,e[i].w)); a+=ret;mi-=ret; e[i].w-=ret; e[i^1].w+=ret; if(!mi) break; } if(a) d[x]=-1; return a; } void DINIC(){ int ans=0; while(bfs()){ int ret=dfs(s,INF); ans+=ret; } printf("%d ",ans); } int main(){ m=read();n=read(); s=n+1;t=n+2; for(int i=1;i<=m;i++){ a[i]=read(); } for(int i=1;i<=n;i++){ c[i].ksum=read(); for(int j=1;j<=c[i].ksum;j++){ c[i].key[j]=read(); } c[i].sum=read(); add(s,i,c[i].sum); add(i,s,0); //与源点连边 } for(int i=1;i<=n;i++){ for(int j=1;j<=c[i].ksum;j++){ int k=c[i].key[j]; if(!las[k]){ add(i,t,a[k]); add(t,i,0); } else{ add(i,las[k],INF); add(las[k],i,0); } las[k]=i; } } DINIC();/*最大流*/ return 0; }