题目大意:迈克在农场工作,农场有 m 个猪舍,每个猪舍有若干只猪,但是迈克不能打开任何一间猪舍。有 n 个顾客前来购买,每个顾客有最大的购买数量,每个顾客可以购买某些猪舍的猪,且顾客可以打开这些猪舍,从中挑选猪仔。重要的是,迈克可以在打开的这些猪舍中重新分配猪仔。由于知道每个猪舍的猪仔数目和顾客的购买情况,求迈克可以卖出的最大数目的猪仔。
解题思路:将每个顾客看成一个点,加上源点、汇点。将每个猪舍的第一位客人与源点相连,容量为猪舍中猪仔的数目,将每个猪圈的前以为顾客与后一位顾客相连,容量为INF,将每位顾客与汇点相连,容量为顾客的最大购买量。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
using namespace std;
int m,n,f,tag[1001];
queue<int> Q;
struct edge{
int from;
int to;
int flow;
int cap;
};
vector<edge>e;
vector<int>adj[1200];
void init(){
f = 0;
for(int i=0;i<=n+m+1;i++)
adj[i].clear();
}
void addedge(int from,int to,int flow,int cap){
e.push_back((edge){from,to,flow,cap});
e.push_back((edge){to,from,flow,0});
int t = e.size();
adj[from].push_back(t - 2);
adj[to].push_back(t - 1);
}
void solve(){
int i,j,a[1200],p[1200];
for( ; ; ){
memset(a,0,sizeof(a));
a[0] = 10000000;
while(!Q.empty())
Q.pop();
Q.push(0);
while(!Q.empty()){
int x = Q.front();
Q.pop();
for(i=0;i<adj[x].size();i++){
int t = adj[x][i] ;
int v = e[t].to;
if(!a[v] && e[t].flow < e[t].cap){
a[v] = a[x] < e[t].cap - e[t].flow ? a[x] : e[t].cap - e[t].flow;
Q.push(v);
p[v] = t ;
}
}
}
if(!a[n+1])
break;
int u = n+1;
for( ; u != 0; u = e[p[u]].from){
e[p[u]].flow += a[n+1] ;
e[p[u] ^ 1].flow -= a[n+1] ;
}
f += a[n+1] ;
}
}
int main(){
int i,j,a,b;
int p[1001],c[1001],x;
while(scanf("%d%d",&m,&n) == 2){
init();
for(i=1;i<=m;i++)
cin >> c[i] ;
memset(tag,0,sizeof(tag));
for(i=1;i<=n;i++){
cin >> a ;
for(j=1;j<=a;j++){
cin >> x ;
if(!tag[x]){
addedge(0,i,0,c[x]);
tag[x] = i ;
}
else
addedge(tag[x],i,0,100000);
}
cin >> b ;
addedge(i,n+1,0,b);
}
solve();
printf("%d
",f);
}
return 0;
}