HDU-4292 Food 简单网络流
依据题中所给定的关系构图,直接网络流。
源点到食物,食物到人,人拆成两个点,流量为1,再从人到饮料。
代码如下:
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #define INF 0x3fffffff #define F(x) (x) #define N(x) (205+(x)) #define CPN(x) (410+(x)) #define D(x) (615+(x)) using namespace std; int n, f, d, head[1005], dis[1005], idx; int que[1000], front, tail; const int SS = 0, TT = 1000; struct Edge { int v, cap, next; }e[200000]; void addedge(int x, int v, int cap) { ++idx; e[idx].v = v, e[idx].cap = cap; e[idx].next = head[x], head[x] = idx; ++idx; e[idx].v = x, e[idx].cap = 0; e[idx].next = head[v], head[v] = idx; } bool bfs() { int pos; memset(dis, 0xff, sizeof (dis)); dis[SS] = front = tail = 0; que[++tail] = SS; while (front != tail) { pos = que[++front]; for (int i = head[pos]; i != -1; i = e[i].next) { if (e[i].cap > 0 && dis[e[i].v] == -1) { dis[e[i].v] = dis[pos] + 1; if (e[i].v == TT) return true; que[++tail] = e[i].v; } } } return false; } int dfs(int u, int flow) { if (u == TT) { return flow; } int f, tf = 0; for (int i = head[u]; i != -1; i = e[i].next) { if (dis[u]+1 == dis[e[i].v] && e[i].cap > 0 && (f = dfs(e[i].v, min(e[i].cap, flow - tf)))) { e[i].cap -= f; e[i^1].cap += f; tf += f; if (tf == flow) return flow; } } if (!tf) dis[u] = -1; return tf; } int dinic() { int ret = 0; while (bfs()) { ret += dfs(SS, INF); } return ret; } int main() { int c; char like[205]; while (scanf("%d %d %d", &n, &f, &d) == 3) { memset(head, 0xff, sizeof (head)); idx = -1; for (int i = 1; i <= f; ++i) { scanf("%d", &c); addedge(SS, F(i), c); } for (int i = 1; i <= d; ++i) { scanf("%d", &c); addedge(D(i), TT, c); } for (int i = 1; i <= n; ++i) { addedge(N(i), CPN(i), 1); scanf("%s", like+1); for (int j = 1; j <= f; ++j) { if (like[j] == 'Y') { addedge(F(j), N(i), 1); } } } for (int i = 1; i <= n; ++i) { scanf("%s", like+1); for (int j = 1; j <= d; ++j) { if (like[j] == 'Y') { addedge(CPN(i), D(j), 1); } } } printf("%d\n", dinic()); } return 0; }