题目大意:
有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 ", dinic(0, n + 1)); } return 0; }