1.题面
http://poj.org/problem?id=3281
2.题意
已知牛的数量n,饮料的种类d,食物的种类,以及每头牛喜欢的食物和饮料,希望你求出最合理的搭配,使最终能吃到饭的牛的数量最多
3.思路
网络流最大流,思路很简单,不说了
4.代码
/*****************************************************************
> File Name: cpp_acm.cpp
> Author: Uncle_Sugar
> Mail: uncle_sugar@qq.com
> Created Time: Mon 03 Oct 2016 19:01:17 CST
*****************************************************************/
# include <cstdio>
# include <cstring>
# include <cctype>
# include <cmath>
# include <cstdlib>
# include <climits>
# include <iostream>
# include <iomanip>
# include <set>
# include <map>
# include <vector>
# include <stack>
# include <queue>
# include <algorithm>
using namespace std;
# define rep(i,a,b) for (i=a;i<=b;i++)
# define rrep(i,a,b) for (i=b;i>=a;i--)
# define mset(aim, val) memset(aim, val, sizeof(aim))
struct QuickIO{
QuickIO(){const int SZ = 1<<20;
setvbuf(stdin ,new char[SZ],_IOFBF,SZ);
setvbuf(stdout,new char[SZ],_IOFBF,SZ);
} //*From programcaicai*//
}QIO;
template<class T>void PrintArray(T* first,T* last,char delim=' '){
for (;first!=last;first++) cout << *first << (first+1==last?'\n':delim);
}
/*
1.see the size of the input data before you select your algorithm
2.cin&cout is not recommended in ACM/ICPC
3.pay attention to the size you defined, for instance the size of edge is double the size of vertex
*/
const int debug = 1;
//# const int size = 10 + ;
const int INF = INT_MAX>>1;
typedef long long ll;
const int MAXN = 510;
const int MAXM = MAXN*MAXN;
struct Edge{
int to, f, nxt;
}edge[MAXM];
int tot = 0;
int head[MAXN];
void init(){
tot = 0;
memset(head, -1, sizeof(head));
}
void addedge(int from, int to, int f){
edge[tot].to = to;edge[tot].f = f;
edge[tot].nxt = head[from]; head[from] = tot++;
edge[tot].to = from;edge[tot].f = 0;
edge[tot].nxt = head[to]; head[to] = tot++;
}
int level[MAXN];
bool bfs(int s, int t){
static queue<int> que;
while (!que.empty()) que.pop();
memset(level, 0, sizeof(level));
que.push(s); level[s] = 1;
while (!que.empty()){
int cur = que.front(); que.pop();
if (cur == t) return true;
for (int e = head[cur]; ~e; e = edge[e].nxt){
int to = edge[e].to, f = edge[e].f;
if (!level[to] && f){
level[to] = level[cur] + 1;
que.push(to);
}
}
}
return false;
}
int dfs(int u, int t, int sup){
if (u == t) return sup;
int ret = 0;
for (int e = head[u]; ~e; e = edge[e].nxt){
int cur = edge[e].to, f = edge[e].f;
if (level[cur] == level[u] + 1 && f){
int mi = min(sup - ret, f);
int tf = dfs(cur, t, mi);
edge[e].f -= tf; edge[e^1].f += tf;
ret += tf;
}
if (ret == sup) return ret;
}
return ret;
}
int Dinic(int s, int t){
int ret = 0;
while (bfs(s, t)) ret += dfs(s, t, INF);
return ret;
}
int main()
{
/*std::ios::sync_with_stdio(false);cin.tie(0);*/
int n, f, d;
while (~scanf("%d%d%d", &n, &f, &d)){
init();
int s = 0, t = f + n + n + d + 1;
for (int i = 1; i <= f; i++) addedge(s, i, 1);
for (int i = 1; i <= n; i++) addedge(f + i, f + n + i, 1);
for (int i = 1; i <= d; i++) addedge(f + n + n + i, t, 1);
for (int i = 1; i <= n; i++){
int a, b, tmp;
scanf("%d%d", &a, &b);
while (a--){
scanf("%d", &tmp);
addedge(tmp, f + i, 1);
}
while (b--){
scanf("%d", &tmp);
addedge(f + n + i, f + n + n + tmp, 1);
}
}
int ans = Dinic(s, t);
printf("%d\n", ans);
}
return 0;
}