poj 3281 Dining(网络流最大流+分点)
2015-04-06 16:32
323 查看
题目大意:有N种食物,和N种饮料.每头牛有喜欢的饮料和食物.问有多少头牛可以同时吃到自己喜欢的饮料和食物.
思路:这道题主要在于建图问题.
添加超级汇点和超级源点自然不用多说了.
正确的建模:源点-->food-->牛(左)-->牛(右)-->drink-->汇点
(转载的)
网上把这个叫做折点,不过我觉得交分点可能比较合适,使需要同时满足的条件都在一条路径上.
思路:这道题主要在于建图问题.
添加超级汇点和超级源点自然不用多说了.
正确的建模:源点-->food-->牛(左)-->牛(右)-->drink-->汇点
(转载的)
网上把这个叫做折点,不过我觉得交分点可能比较合适,使需要同时满足的条件都在一条路径上.
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define MAXN 2020 #define MAXM 8080 #define INF 0x7fffffff int dep[MAXN], head[MAXN], gap[MAXN], cur[MAXN]; int cnt; struct edge { int v; int cap; int flow; int next; }edg[MAXM]; void init() { cnt = 0; memset(head, -1, sizeof(head)); } void addedge(int u, int v, int w, int rw=0) { edg[cnt].v = v; edg[cnt].cap = w; edg[cnt].flow = 0; edg[cnt].next = head[u]; head[u] = cnt++; edg[cnt].v = u; edg[cnt].cap = rw; edg[cnt].flow = 0; edg[cnt].next = head[v]; head[v] = cnt++; } int Q[MAXN]; void BFS(int start, int end) { memset(gap, 0, sizeof(gap)); memset(dep, -1, sizeof(dep)); gap[0] = 1; dep[end] = 0; int front =0,rear = 0; Q[rear++] = end; while (front != rear) { int u = Q[front++]; for (int i = head[u]; i != -1; i = edg[i].next) { int v = edg[i].v; if (dep[v] != -1)continue; dep[v] = dep[u] + 1; gap[dep[v]]++; Q[rear++] = v; } } } int S[MAXN]; int sap(int start, int end, int n) { memcpy(cur, head, sizeof(head)); BFS(start, end); int top = 0; int u = start; int ans = 0; while (dep[start] < n) { if (u == end) { int Min = INF; int inser; for (int i = 0; i < top; i++) if (Min > edg[S[i]].cap - edg[S[i]].flow) { Min = edg[S[i]].cap - edg[S[i]].flow; inser = i; } for (int i = 0; i < top; i++) { edg[S[i]].flow += Min; edg[S[i] ^ 1].flow -= Min; } ans += Min; top = inser; u = edg[S[top] ^ 1].v; continue; } bool flag = false; int v; for (int i = cur[u]; i != -1; i = edg[i].next) { v = edg[i].v; if (edg[i].cap - edg[i].flow&&dep[v] + 1 == dep[u]) { cur[u] = i; flag = true; break; } } if (flag) { S[top++] = cur[u]; u = v; continue; } int Min = n; for (int i = head[u]; i != -1; i = edg[i].next) { if (edg[i].cap - edg[i].flow&&Min > dep[edg[i].v]) { Min = dep[edg[i].v]; cur[u] = i; } } gap[dep[u]]--; if (!gap[dep[u]])return ans; dep[u] = Min + 1; gap[dep[u]]++; if (u != start)u = edg[S[--top] ^ 1].v; } return ans; } int main() { int n, f, d; while (~scanf("%d%d%d", &n, &f, &d)) { init(); int E = 2*n + f + d + 1; for (int i = 1; i <= f; i++) addedge(0, i, 1); for (int i = 1; i <= d; i++) addedge(2*n + f + i, E, 1); for (int i = 1; i <= n; i++) addedge(f + i, f + i+n, 1); int f1, d1,k; for (int i = 1; i <= n; i++) { scanf("%d%d", &f1, &d1); while (f1--) { scanf("%d", &k); addedge(k, f + i, 1); } while (d1--) { scanf("%d", &k); addedge(f + i + n, 2 * n + f + k, 1); } } printf("%d\n", sap(0, E, E)); } }
相关文章推荐
- poj 3281 Dining (最大网络流)
- POJ 3281 Dining(网络流,最大流ek记录板子)
- poj 3281 Dining 网络流-最大流-建图的题
- POJ 3281 Dining(网络流最大匹配)
- POJ 3281 - Dining(网络流‘最大流)
- POJ 3281 Dining 网络流最大流
- POJ 3281-Dining(网络流_最大流_ISAP算法+拆点)
- poj 3281 Dining 【图论-网络流-最大流-EK&Ford-Fulkerson】
- poj 3281 Dining 最大网络流
- POJ 3281 Dining 【网络流建模汇总】最大流
- 【网络流#7】POJ 3281 Dining 最大流 - 《挑战程序设计竞赛》例题
- poj 3281 Dining(网络流最大流)
- POJ 3281 Dining (网络流最大流 拆点建图 EK Dinic)
- poj 3281 Dining 网络流-最大流-建图的题
- POJ 3281 Dining (网络流最大流 拆点建图 Edmonds-Karp算法)
- POJ-3281 Dining (最大流[Ford-Fulkerson])
- poj 3281 Dining 最大流
- POJ 3281 Dining & HDU 4292 Food【最大流】
- POJ 3281 Dining(最大流)
- poj 3281 Dining(拆点+最大流)