poj 3281 Dining

来源:互联网 发布:如何摆脱抑郁症知乎 编辑:程序博客网 时间:2024/06/18 07:00

题目:

Description

Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others.

Farmer John has cooked fabulous meals for his cows, but he forgot to check his menu against their preferences. Although he might not be able to stuff everybody, he wants to give a complete meal of both food and drink to as many cows as possible.

Farmer John has cooked F (1 ≤ F ≤ 100) types of foods and prepared D (1 ≤ D ≤ 100) types of drinks. Each of his N (1 ≤ N ≤ 100) cows has decided whether she is willing to eat a particular food or drink a particular drink. Farmer John must assign a food type and a drink type to each cow to maximize the number of cows who get both.

Each dish or drink can only be consumed by one cow (i.e., once food type 2 is assigned to a cow, no other cow can be assigned food type 2).

Input

Line 1: Three space-separated integers: NF, and D 
Lines 2..N+1: Each line i starts with a two integers Fi and Di, the number of dishes that cow i likes and the number of drinks that cow i likes. The next Fi integers denote the dishes that cow i will eat, and the Di integers following that denote the drinks that cow i will drink.

Output

Line 1: A single integer that is the maximum number of cows that can be fed both food and drink that conform to their wishes

Sample Input

4 3 32 2 1 2 3 12 2 2 3 1 22 2 1 3 1 22 1 1 3 3

Sample Output

3

Hint

One way to satisfy three cows is: 
Cow 1: no meal 
Cow 2: Food #2, Drink #2 
Cow 3: Food #1, Drink #1 
Cow 4: Food #3, Drink #3 
The pigeon-hole principle tells us we can do no better since there are only three kinds of food or drink. Other test data sets are more challenging, of course.

有N头牛,F个食物,D个饮料。每头牛都有特定喜欢的食物和饮料若干,每个饮料和食物都只能提供给一头牛,每头牛必须要同时获得一个食物和一个饮料才能得到满足。首先输入N,F,D表示N头牛,F个食物,D个饮料,接下来N行输入每头牛的喜好,每一行输入两个整数f和d表示该头牛喜欢的食物和饮料总数,接下来依次输入f个食物的序号和d个食物的序号。输入完毕之后,要求输出最多能满足多少头牛。

题意:这是一个规划问题,给N头牛分配F个食物和D个饮料。观察题目的要求,当一个食物或一个饮料提供给了一头牛,就不能提供给其他的牛,如果用一个路径表示,食物指向牛,牛指向饮料就表示了一个分配方案,再加上起点和汇点,就是一个最大流路径了,所以自然而然想到这道题用网络流来建模。首先计算一下网络里有多少个节点,一个起点,一个汇点,f个食物节点,d个饮料节点,至于要多少个牛的节点是这道题的重点,一头牛可能可以同时获得一个食物和一个饮料,也可能只能获得一个食物或一个饮料,所以这是一个二分配的问题,要建立两个牛的节点,节点之间相连,流通值为1的时候表示能同时分配食物和饮料。所以总共有1(起点)+f(食物)+2*n(牛)+d(饮料)+1(汇点)个节点。初始状态时起点到每个食物之间的边,每个饮料到汇点的边,每头牛之间的边都是1,输入食物和饮料之后,这些食物和饮料与牛之间的边也是1。然后就可以用最大流的算法得出汇点的最大流也就是最多能满足的牛的数目。
#include<iostream>#include<stdio.h>#include<queue>using namespace std;#define MAXN 500int map[MAXN][MAXN];int flow[MAXN][MAXN];int min_flow[MAXN];int pre[MAXN];bool bfs(int m, int s, int t){memset(min_flow, 0, sizeof(min_flow));min_flow[s] = INT_MAX;queue<int> q;q.push(s);while (!q.empty()){int u = q.front();q.pop();for (int v = s; v < m; ++v){if (min_flow[v] == 0 && map[u][v] > flow[u][v]){pre[v] = u;q.push(v);min_flow[v] = min(min_flow[u], map[u][v] - flow[u][v]);}}}if (min_flow[t] == 0)return false;return true;}int max_flow(int m, int s, int t){int res = 0;memset(pre, 0, sizeof(pre));memset(flow, 0, sizeof(flow));while (bfs(m, s, t)){for (int u = t; u != s; u = pre[u]){flow[pre[u]][u] += min_flow[t];flow[u][pre[u]] -= min_flow[t];}res += min_flow[t];}return res;}int main(){int n, f, d;while (scanf_s("%d%d%d", &n, &f, &d) != EOF){memset(map, 0, sizeof(map));for (int i = 1; i <= f; i++)map[0][i] = 1;              //源点-->foodfor (int i = 1; i <= d; i++)map[i + 2*n + f][2*n + f + d + 1] = 1;    //drink-->汇点for (int i = 1; i <= n; i++)map[f + i][f + n + i] = 1; //牛指向牛for (int i = 1; i <= n; ++i){int t1, t2;cin >> t1 >> t2;while (t1--){int food;cin >> food;map[food][f + i] = 1;}while (t2--){int drink;cin >> drink;map[f + i + n][2 * n + f + drink] = 1;}}int res = max_flow(f+2*n+d+2, 0, f+2*n+d+1);cout << res << endl;}return 0;}


原创粉丝点击