题目链接
题目大意:有N头牛,F个食物,D个饮料。
N头牛每头牛有一定的喜好,只喜欢几个食物和饮料。
每个食物和饮料只能给一头牛。一头牛只能得到一个食物和饮料。
而且一头牛必须同时获得一个食物和一个饮料才能满足。问至多有多少头牛可以获得满足。
大体思路:
最大流建图是把食物和饮料放在两端。一头牛拆分成两个点,两点之间的容量为1.喜欢的食物和饮料跟牛建条边,容量为1.
加个源点和汇点。源点与食物、饮料和汇点的边容量都是1,表示每种食物和饮料只有一个。
输入:
4(头牛) 3(种食物) 3(种饮料)
2 2 1 2 3 1
2 2 2 3 1 2
2 2 1 3 1 2
2 1 1 3 3
(第i头牛能吃的食物种类数量)(第i头牛能喝的饮料种类数量)(N1个食物)(N2个饮料)
//源点-->food-->牛(左)-->牛(右)-->drink-->汇点
//精髓就在这里,牛拆点,确保一头牛就选一套food和drink的搭配
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 3000;
const int INF = 0x3f3f3f3f;
struct node {
int to, w, next;
} Edge[maxn << 1];
int Head[maxn], cur[maxn], level[maxn], cnt;
vector<int> drink[maxn], food[maxn];
void add(int u, int v, int w) {
Edge[cnt] = (node) {v, w, Head[u]};
Head[u] = cnt++;
Edge[cnt] = (node) {u, 0, Head[v]};
Head[v] = cnt++;
}
bool bfs(int s, int e) {
memset(level, -1, sizeof(level));
level[s] = 0;
queue<int> q;
q.push(s);
while(!q.empty()) {
int now = q.front();
q.pop();
for(int i = Head[now]; ~i; i = Edge[i].next) {
int to = Edge[i].to;
if(level[to] == -1 && Edge[i].w) {
level[to] = level[now] + 1;
q.push(to);
}
}
}
return level[e] != -1;
}
int dfs(int s, int e, int f) {
if(s == e) return f;
int flow = 0, d;
for(int &i = cur[s]; ~i; i = Edge[i].next) {
int to = Edge[i].to, w = Edge[i].w;
if(level[to] > level[s] && w && (d = dfs(to, e, min(f, w)))) {
flow += d;
Edge[i].w -= d;
Edge[i ^ 1].w += d;
f -= d;
if(!f) break;
}
}
if(!flow) level[s] = -1;
return flow;
}
int max_flow(int s, int e) {
int flow = 0;
while(bfs(s, e)) {
memcpy(cur, Head, sizeof(Head));
flow += dfs(s, e, INF);
}
return flow;
}
int main()
{
int n, f, d;
scanf("%d %d %d", &n, &f, &d);
for(int i = 1; i <= n; i++) {
int num1, num2, u;
scanf("%d %d", &num1, &num2);
for(int j = 0; j < num1; j++) {
scanf("%d", &u);
food[i].push_back(u);
}
for(int j = 0; j < num2; j++) {
scanf("%d", &u);
drink[i].push_back(u);
}
}
cnt = 0;
memset(Head, -1, sizeof(Head));
for(int i = 0; i < f; i++) {
add(0, i + 1, 1);
}
for(int i = 1; i <= n; i++) {
add(i + f, i + f + n, 1);
for(int j = 0; j < food[i].size(); j++) {
add(food[i][j], i + f, 1);
}
for(int j = 0; j < drink[i].size(); j++) {
add(i + f + n, 2 * n + f + drink[i][j], 1);
}
}
for(int i = 0; i < d; i++) {
add(2 * n + f + i + 1, 2 * n + f + d + 1, 1);
}
int v = max_flow(0, 2 * n + f + d + 1);
printf("%d\n", v);
}