下周要给学弟讲网络流了, 最近复习了一下发现了这题,这道题主要考察的就是构图, 如果只有食物或者饮料那么这
题就很水了, 由于每一头牛都要有和一种食物还有一种饮料匹配那么可以考虑将牛拆成两个点然后左边和食物相连右
边和饮料相连, 食物和源点相连, 饮料和汇点相连。
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <ctime>
#include <algorithm>
using namespace std;
const int N = 505;
const int M = N * N * 2;
typedef int LL;
const LL INF = 1000000000;
struct Dinic {
struct Edge {
int v;
LL cap, flow;
Edge* next, * pair;
void init(int a, LL b, Edge* e1, Edge* e2) {
v = a, cap = b, flow = 0, next = e1, pair = e2;
}
};
Edge* head[N], * used[N];
Edge* it;
int lev[N], que[N];
Edge E[M];
int n, s, t;
LL maxFlow;
void init(int n, int s, int t) {
it = E;
this->n = n;
this->s = s, this->t = t;
for (int i = 0; i < n; i++)
head[i] = 0;
}
void add(int u, int v, LL c) {
it->init(v, c, head[u], it + 1);
head[u] = it++;
it->init(u, 0, head[v], it - 1);
head[v] = it++;
}
bool bfs() {
for (int i = 0; i < n; lev[i++] = -1);
lev[s] = 1;
int st = 0, ed = 0;
que[ed++] = s;
while (st < ed) {
int u = que[st++];
for (Edge* e = head[u]; e; e = e->next) {
int v = e->v;
if (lev[v] == -1 && e->cap > e->flow) {
lev[v] = lev[u] + 1;
que[ed++] = v;
}
}
}
return lev[t] != -1;
}
LL dfs(int u, LL f) {
if (u == t) return f;
for (Edge* & e = used[u]; e; e = e->next) {
int v = e->v;
if (e->cap > e->flow && lev[v] == lev[u] + 1) {
LL tmp = dfs(v, min(e->cap - e->flow, f));
if (tmp > 0) {
e->flow += tmp;
e->pair->flow -= tmp;
return tmp;
}
}
}
return 0;
}
void run() {
maxFlow = 0;
while (bfs()) {
for (int i = 0; i < n; i++)
used[i] = head[i];
LL f = 1;
while (f) {
f = dfs(s, INF);
maxFlow += f;
}
}
}
}G;
int main() {
int a, b, c, f, d, s, t, n, tmp;
while (~scanf("%d%d%d", &c, &a, &b)) {
n = a + b + 2 * c + 2;
s = 0, t = n - 1;
G.init(n, s, t);
for (int i = 1; i <= a; i++)
G.add(s, i, 1);
for (int i = 1; i <= b; i++)
G.add(i + a + 2 * c, t, 1);
for (int i = 1; i <= c; i++) {
scanf("%d%d", &f, &d);
while (f--) {
scanf("%d", &tmp);
G.add(tmp, a + i, 1);
}
while (d--) {
scanf("%d", &tmp);
G.add(a + c + i, tmp + a + 2 * c, 1);
}
G.add(i + a, i + c + a, 1);
}
G.run();
printf("%d\n", G.maxFlow);
}
return 0;
}