题目大意:
有M个猪圈,每个猪圈都有把锁,卖猪的本身是没有钥匙的,现在有N个顾客要来买猪,而且第i个顾客有a[i]把锁的钥匙,能打开k1,k2,k3...kai的猪圈,称这个时候,你可以调整k1,k2,k3...kai号猪圈里面猪的个数。现在已知每个客户要买多少猪,有哪些锁。问你一天最多能卖出去多少猪。
解题思路:
把顾客当作除了源点和汇点的节点,并且设置一个源点和汇点。
把第一次访问ai个猪圈的顾客与源点添加一条边,容量为开始时猪圈中猪的数目。把在他之后第二个访问该猪圈的顾客与他再添加一条边,容量为INF。以此类推。
再把每个顾客与汇点添加一条边容量为要买猪的个数。
这样构图就完成了。然后直接求网络流即可
代码:
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
typedef struct node{
int v, cap, nxt;
node(int _v = 0, int _cap = 0, int _nxt = 0): v(_v), cap(_cap), nxt(_nxt){}
}Edge;
const int maxn = 200;
const int maxm = 2e4 + 10;
const int INF = 0x3f3f3f3f;
int tot;
Edge edge[maxm];
int dis[maxn];
int head[maxm], num[1005], vis[maxn];
inline int Min(int a, int b){
return a < b ? a : b;
}
void add(int u, int v, int cap){
edge[tot] = Edge(v, cap, head[u]);
head[u] = tot++;
edge[tot] = Edge(u, 0, head[v]);
head[v] = tot++;
}
int bfs(int s, int t){
queue<int> q;
while(!q.empty()) q.pop();
memset(dis, 0, sizeof(dis));
q.push(s); dis[s] = 1;
while(!q.empty()){
int u = q.front(); q.pop();
if(u == t) break;
for(int i = head[u]; ~i; i = edge[i].nxt){
Edge &e = edge[i];
if(!dis[e.v] && e.cap){
dis[e.v] = dis[u] + 1;
q.push(e.v);
}
}
}
return dis[t];
}
int dfs(int u, int v, int f){
if(u == v) return f;
int sum = 0;
for(int i = head[u]; ~i; i = edge[i].nxt){
Edge &e = edge[i];
if(e.cap && dis[e.v] == dis[u] + 1){
int ret = dfs(e.v, v, Min(f, e.cap));
sum += ret; f -= ret;
e.cap -= ret; edge[i^1].cap += ret;
}
}
return sum;
}
int dinic(int s, int t){
int ret = 0;
while(bfs(s, t))
ret += dfs(s, t, INF);
return ret;
}
int main(){
int a, k, m, n, sum, val;
while(~scanf("%d%d", &m, &n)){
tot = 0;
memset(vis, 0, sizeof(vis));
memset(head, -1, sizeof(head));
for(int i = 1; i <= m; ++i){
scanf("%d", &num[i]);
}
for(int i = 1; i <= n; ++i){
scanf("%d", &a);
sum = 0;
for(int j = 1; j <= a; ++j){
scanf("%d", &k);
if(!vis[k]){ vis[k] = i; sum += num[k]; }
else {
if(vis[k] == i) continue;
add(vis[k], i, INF);
vis[k] = i;
}
}
scanf("%d", &val);
if(sum > 0) add(0, i, sum);
add(i, n + 1, val);
}
printf("%d\n", dinic(0, n + 1));
}
return 0;
}