hdu 4292 Food【拆点网络流】

来源:互联网 发布:java命令如何打jar包 编辑:程序博客网 时间:2024/05/02 13:24

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4292

解法:拆人

代码:

#include <stdio.h>  #include <ctime>  #include <math.h>  #include <limits.h>  #include <complex>  #include <string>  #include <functional>  #include <iterator>  #include <algorithm>  #include <vector>  #include <stack>  #include <queue>  #include <set>  #include <map>  #include <list>  #include <bitset>  #include <sstream>  #include <iomanip>  #include <fstream>  #include <iostream>  #include <ctime>  #include <cmath>  #include <cstring>  #include <cstdio>  #include <time.h>  #include <ctype.h>  #include <string.h>  #include <assert.h>  using namespace std;const int MAXN = 50010;//点数的最大值const int MAXM = 90001000;//边数的最大值const int INF = 0x3f3f3f3f;struct Edge{    int to, next, cap, flow;}edge[MAXM];//注意是MAXMint tol;int head[MAXN];int gap[MAXN], dep[MAXN], pre[MAXN], cur[MAXN];void init(){    tol = 0;    memset(head, -1, sizeof(head));}//加边,单向图三个参数,双向图四个参数void addedge(int u, int v, int w, int rw = 0){    edge[tol].to = v; edge[tol].cap = w; edge[tol].next = head[u];    edge[tol].flow = 0; head[u] = tol++;    edge[tol].to = u; edge[tol].cap = rw; edge[tol].next = head[v];    edge[tol].flow = 0; head[v] = tol++;}//输入参数:起点、终点、点的总数//点的编号没有影响,只要输入点的总数int sap(int start, int end, int N){    memset(gap, 0, sizeof(gap));    memset(dep, 0, sizeof(dep));    memcpy(cur, head, sizeof(head));    int u = start;    pre[u] = -1;    gap[0] = N;    int ans = 0;    while (dep[start] < N)    {        if (u == end)        {            int Min = INF;            for (int i = pre[u]; i != -1; i = pre[edge[i ^ 1].to])                if (Min > edge[i].cap - edge[i].flow)                    Min = edge[i].cap - edge[i].flow;            for (int i = pre[u]; i != -1; i = pre[edge[i ^ 1].to])            {                edge[i].flow += Min;                edge[i ^ 1].flow -= Min;            }            u = start;            ans += Min;            continue;        }        bool flag = false;        int v;        for (int i = cur[u]; i != -1; i = edge[i].next)        {            v = edge[i].to;            if (edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u])            {                flag = true;                cur[u] = pre[v] = i;                break;            }        }        if (flag)        {            u = v;            continue;        }        int Min = N;        for (int i = head[u]; i != -1; i = edge[i].next)            if (edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)            {                Min = dep[edge[i].to];                cur[u] = i;            }        gap[dep[u]]--;        if (!gap[dep[u]])return ans;        dep[u] = Min + 1;        gap[dep[u]]++;        if (u != start) u = edge[pre[u] ^ 1].to;    }    return ans;}int n, f, d;char s[300];int F[300], D[300];int main(){    while (~scanf("%d%d%d", &n, &f, &d))    {        init();        for (int i = 1; i <= f; i++) scanf("%d", &F[i]);        for (int i = 1; i <= d; i++) scanf("%d", &D[i]);        for (int i = 1; i <= f; i++) addedge(0, i, F[i]);        for (int i = 1; i <= d; i++) addedge(f + n + n + i, f + n + n + d + 1, D[i]);        for (int i = 1; i <= n; i++) addedge(f + i, f + n + i, 1);        for (int i = 1; i <= n; i++)        {            scanf("%s", s);            for (int k = 0; k < f; k++)//食物            {                if (s[k] == 'Y')                    addedge(k + 1, f + i , 1);            }        }        for (int i = 1; i <= n; i++)        {            scanf("%s", s);            for (int k = 0; k < d; k++)//水            {                if (s[k] == 'Y')                    addedge(i + f + n, f + n + n + k + 1, 1);            }        }        int ans = sap(0, f + d + n + n + 1, f + d + n + n + 2);        printf("%d\n",ans);    }    return 0;}
0 0