题目:
m个猪圈,n个顾客,每个猪圈里面有一定数量的猪,每个顾客有一定的需求量。求最多可以卖出多少条猪?
这里注意有一个前提条件,就是一个顾客开了一个猪圈之后,后 面的话,可以将这个猪圈里面的猪 拉到其他猪圈里去。
此题关键就是 建立图结构,因为最大流问题,我们可以用 EK 模板来套。
此图里面有三层,第一层就是源点,第二层顾客,第三层是汇点。
总的来说,源点与顾客连,顾客与汇点连。注意,猪圈不在图里面。
顾客与汇点连的话,权值就是 顾客所需要的猪的数量,比较好理解。
源点与顾客连,前提是 该顾客是第一个开某个猪圈的人。 然后,将该顾客连向后面也需要开此猪圈的人,权值为MAX
我的理解是,第一个打开猪圈的客户可以取得所有的猪,故源点和客户之间的连线容量就表示第一个打开猪圈的人虽能够得到的数量..
然后接下来的每一个人与前一个打开猪圈的人之间连线,容量为MAX,因为可以从别的猪圈调猪过来
一开始,总是 Runtime error,以为是超时,后来发现算法没问题。最后查出来发现,是因为 pre数组开小了。
#include <iostream>
#include <queue>
using namespace std;
#define MAXV 110
#define PIGNUM 1005
#define MAX 1<<29
int map[MAXV][MAXV];
int pre[PIGNUM];
int flow[MAXV];
int n;
queue<int>q;
int BFS(){
int i;
memset(pre,-1,sizeof(pre));
while(!q.empty())
q.pop();
pre[0] = 0;
flow[0] = MAX;
q.push(0);
while(!q.empty()){
int index = q.front();
q.pop();
if(index == n+1)
break;
for(i=1;i<=n+1;i++){
if(map[index][i]>0&&pre[i]==-1){
pre[i] = index;
flow[i] = min(flow[index],map[index][i]);
q.push(i);
}
}
}
if(pre[n+1]==-1)
return -1;
else
return flow[n+1];
}
int maxFlow(){
int increasement = 0;
int sumflow = 0;
while((increasement = BFS())!=-1){
int k = n+1;
while(k!=0){
int last = pre[k];
map[last][k] -= increasement;
map[k][last] += increasement;
k = last;
}
sumflow += increasement;
}
return sumflow;
}
int main(){
int m,i,j,k;
int pigNum[PIGNUM];
while(cin>>m>>n){
memset(map,0,sizeof(map));
for(i=1;i<=m;i++)
cin>>pigNum[i];
for(i=1;i<=n;i++){
cin>>j;
while(j--){
cin>>k;
if(pre[k] == 0)
map[0][i] += pigNum[k];
else
map[pre[k]][i] = MAX;
pre[k] = i;
}
cin>>map[i][n+1];
}
cout<<maxFlow()<<endl;
}
return 0;
}