自己的第一道最大流,还是要纪念一下的。
转化成网络流即可。将顾客看成除了源点和汇点以外的其他节点,再添加源点和汇点即可。
因为只要猪圈打开了猪就可以任意调整,所以相对同一个猪圈,后打开的人从猪圈里买到的猪的理论值为无限大。源点和打开猪圈第一人之间的容量为这个猪圈内住的数量。顾客节点和汇点的容量为顾客需要购,买猪的数量。构造网络,求源点到汇点的最大流。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define INF 30000000
#define maxn 105
using namespace std;
int map[maxn][maxn];
int p[maxn];
int s,t,n;
int N,M;
//求最大流模板
bool bfs(int start,int end){
bool flag[maxn];
memset(p,-1,sizeof(p));
memset(flag,0,sizeof(flag));
queue<int> que;
que.push(start);
flag[start]=1;
while(!que.empty()){
int e=que.front();
if(e==end) return true;
que.pop();
for(int i=0;i<=N+1;i++){
if(map[e][i]&&!flag[i]){
flag[i]=1;
p[i]=e;
que.push(i);
}
}
}
return false;
}
int EK(int start,int end){
int u,flow=0,mn;
while(bfs(start,end)){
mn=INF;
u=end;
while(p[u]!=-1){
mn=min(mn,map[p[u]][u]);
u=p[u];
}
u=end;
flow+=mn;
while(p[u]!=-1){
map[p[u]][u]-=mn;
map[u][p[u]]+=mn;
u=p[u];
}
}
return flow;
}
//初始化
void init(){
int num;
int k;
int house[1010];
int last[1010];
memset(last,0,sizeof(last));
memset(map,0,sizeof(map));
scanf("%d%d",&M,&N);
s=0;
t=N+1;
for(int i=1;i<=M;++i) scanf("%d",&house[i]);
for(int i=1;i<=N;++i){
scanf("%d",&num);
for(int j=0;j<num;++j){
scanf("%d",&k);
if(last[k]==0) map[s][i]+=house[k];
else map[last[k]][i]=INF;
last[k]=i;
}
scanf("%d",&map[i][t]);
}
/*
for(int i=0;i<=N+1;++i){
for(int j=0;j<=N+1;++j) cout<<map[i][j]<<" ";
cout<<endl;
}
*/
}
int main()
{
init();
cout<<EK(s,t)<<endl;
return 0;
}