[洛谷 P2891][caioj 1116][USACO07OPEN] 吃饭Dining --- dinic最大流
2018-02-28 11:43
197 查看
【题目描述】
有 F (1 ≤ F ≤ 1000)块不同的肉(编号1~F) 和 D (1 ≤ D ≤ 1000) 罐不同的饮料(编号1~D)。有 N (1 ≤ N ≤ 1000)头牛(编号1~N)。每头牛有自己喜欢的肉和饮料。每块肉和每罐饮料只能供给一头牛使用。
求最多能满足多少头牛能同时享用到自己喜欢的肉和饮料。(注意某头牛得到满足,不要求享用自己所有喜欢的肉和饮料,只要喜欢的肉的其中一块和自己喜欢的饮料其中一罐就可以算满足)
【输入格式】
第一行:三个整数 N, F, and D
下来N行。每行描述一头牛。每行开头两个整数Fi和Di,Fi表示该牛喜欢的肉的数目,Di表示它喜欢的饮料的数目。下来Fi个数,各表示它喜欢的肉的编号,再来Di个数,表示它喜欢的饮料的编号。(注意Fi和Di有可能为0)
【输出格式】
一个整数,最大满足的牛的数目。(免费提示:答案中的牛必须同时享用肉和饮料,有些牛Fi或Di为0,是绝对不能选的)
Sample Input
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
Sample Output
3
分析
建图: 源点->食物->牛1->牛2->饮料->汇点 {边权均为1}此处将牛拆为两点,从而满足牛只使用一样食物的限制
代码
#include <cstdio> #include <cstdlib> #include <cstring> #include <vector> #include <queue> #define IL inline #define open(s) freopen(s".in","r",stdin); freopen(s".out","w",stdout); #define close fclose(stdin); fclose(stdout); #define INF 0x7f7f7f7f using namespace std; inline int read() { char c=getchar(); int sum=0,k=1; for(;'0'>c || c>'9';c=getchar()) if(c=='-') k=-1; for(;'0'<=c && c<='9';c=getchar()) sum=sum*10+c-'0'; return sum*k; } struct Edge { int to, cap, flow; }; int n, m, S, T; vector<Edge> edge; vector<int> G[50005]; int cur[50005]; int dep[50005]; IL int min_(int x,int y) { return x < y ? x : y; } IL void add(int u, int v, int c) { edge.push_back((Edge){v, c, 0}); edge.push_back((Edge){u, 0, 0}); G[u].push_back(m++); G[v].push_back(m++); } IL bool Bfs() { queue<int>q; memset(dep, 0, sizeof(dep)); q.push(S); dep[S] = 1; for(int t = 1, u; t;) { u = q.front(); q.pop(); --t; for(int i = 0, s = G[u].size(); i < s; ++i) { Edge e = edge[G[u][i]]; if(!dep[e.to] && e.flow < e.cap) { q.push(e.to); ++t; dep[e.to] = dep[u] + 1; } } } return dep[T]; } IL int Dfs(int u, int a) { if(u == T || !a) return a; int flow = 0, f; for(int &i = cur[u], s = G[u].size(); i < s; ++i) { Edge &e = edge[G[u][i]]; if(dep[e.to] == dep[u] + 1 && (f = Dfs(e.to, min_(a, e.cap - e.flow))) > 0) { e.flow += f; edge[G[u][i] ^ 1].flow -= f; flow += f; a -= f; if(!a) break; } } return flow; } IL int maxflow() { int flow = 0; for(; Bfs();) { memset(cur, 0, sizeof(cur)); flow += Dfs(S, INF); } return flow; } int main() { open("1116"); int n1 = read(), n2 = read(), n3 = read(); S = 0; T = (n1 << 1) + n2 + n3 + 1; for(int i = 1; i <= n2; ++i) add(S, (n1 << 1) + i, 1); for(int i = 1; i <= n3; ++i) add((n1 << 1) + n2 + i, T, 1); for(int i = 1, x, y, z, f, p1, p2; i <= n1; ++i) { x = read(); y = read(); f = (x && y); p1 = (i << 1) - 1; p2 = p1 + 1; if(f) add(p1, p2, 1); for(; x; --x) { z = read(); if(f) add((n1 << 1) + z, p1, 1); } for(; y; --y) { z = read(); if(f) add(p2, (n1 << 1) + n2 + z, 1); } } printf("%d\n", maxflow()); close; return 0; }
相关文章推荐
- [网络流] 洛谷P2891 [USACO07OPEN]吃饭Dining
- P2891 [USACO07OPEN]吃饭Dining(最大流+拆点)
- [洛谷 P2857][caioj 1120] 牛选牛圈 --- 二分+网络流-最大流
- [caioj 1115] 网络流入门1 --- dinic最大流
- (POJ 3281)Dining --最大流,匹配建图,Dinic
- bzoj 1711: [Usaco2007 Open]Dining吃饭 (最大流)
- bzoj1711 [Usaco2007 Open]Dining吃饭 最大流
- [USACO07OPEN]吃饭Dining
- BZOJ1711 [ Usaco2007 Open ]Dining吃饭 拆点最大流
- POJ 3281 Dining(最大流-Dinic)
- 【哈理工OJ 750题纪念!】Hrbust 2200 Escaping【建图+最大流-------Dinic】
- caioj1099 线段树(区间修改+求区间最大值
- [USACO07OPEN]吃饭Dining
- [caioj 1117]路径中的最长边最小 --- 二分 + dinic最大流
- caioj1099 线段树(区间修改+求区间最大值
- 【最大流】【Dinic】bzoj1711 [Usaco2007 Open]Dingin吃饭
- 【BZOJ1711】[Usaco2007 Open]Dining吃饭【最大流】
- [bzoj1711][Usaco2007 Open]Dining吃饭 最大流
- [最大流]BZOJ 1711: [Usaco2007 Open]Dining吃饭 题解
- bzoj 1711: [Usaco2007 Open]Dining吃饭(最大流)