1. 程式人生 > >hdu 4292 Food 【圖論-網路流-最大流-Dinic】

hdu 4292 Food 【圖論-網路流-最大流-Dinic】

                                    Food
    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Problem Description
  You, a part-time dining service worker in your college’s dining hall, are now confused with a new problem: serve as many people as possible.
  The issue comes up as people in your college are more and more difficult to serve with meal: They eat only some certain kinds of food and drink, and with requirement unsatisfied, go away directly.
  You have prepared F (1 <= F <= 200) kinds of food and D (1 <= D <= 200) kinds of drink. Each kind of food or drink has certain amount, that is, how many people could this food or drink serve. Besides, You know there’re N (1 <= N <= 200) people and you too can tell people’s personal preference for food and drink.
  Back to your goal: to serve as many people as possible. So you must decide a plan where some people are served while requirements of the rest of them are unmet. You should notice that, when one’s requirement is unmet, he/she would just go away, refusing any service.

Input
  There are several test cases.
  For each test case, the first line contains three numbers: N,F,D, denoting the number of people, food, and drink.
  The second line contains F integers, the ith number of which denotes amount of representative food.
  The third line contains D integers, the ith number of which denotes amount of representative drink.
  Following is N line, each consisting of a string of length F. e jth character in the ith one of these lines denotes whether people i would accept food j. “Y” for yes and “N” for no.
  Following is N line, each consisting of a string of length D. e jth character in the ith one of these lines denotes whether people i would accept drink j. “Y” for yes and “N” for no.
  Please process until EOF (End Of File).

Output
  For each test case, please print a single line with one integer, the maximum number of people to be satisfied.

Sample Input
4 3 3
1 1 1
1 1 1
YYN
NYY
YNY
YNY
YNY
YYN
YYN
NNY

Sample Output
3

題目大意:有n個人,每個人都有自己喜歡的食物和飲料,先有F中食物,D中飲料,並給出每個人的喜好,讓你求所給食物和飲料最多能滿足多少人的需求
注:本題和poj3281差不多,現給出我做poj3281時的文章連結:

http://blog.csdn.net/xingdragon/article/details/70237266
解題思路也在上面連結的文章裡

知識點:最大流

**所用演算法:**Dinic

AC程式碼:

//Dinic             AC
//Ford-Fulkerson    Time limit
//EK                Time limit
# include <cstdio>
# include <cstring>
# include <queue>

using namespace std;

# define MAXN 10005
# define MAXM 200005  //陣列開小了 超時了好多次
# define INF 1 << 30

struct EDGE
{
    int to;
    int w;
    int next;
}edge[MAXM];

int tot;
int head[MAXN];
int dis[MAXN];

int min(int a, int b)
{
    return a > b ? b : a;
}

void Init()
{
    tot = 0;
    memset(head, -1, sizeof(head));
}

void Addedge(int u, int v, int w)
{
    edge[tot].to = v;
    edge[tot].w = w;
    edge[tot].next = head[u];
    head[u] = tot++;

    edge[tot].to = u;
    edge[tot].w = 0;
    edge[tot].next = head[v];
    head[v] = tot++;
}

bool Bfs(int s, int t)
{
    memset(dis, 0, sizeof(dis));
    queue<int> que;
    dis[s] = 1;
    que.push(s);
    while (!que.empty())
    {
        int u = que.front(); que.pop();
        for (int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if (dis[v] == 0 && edge[i].w > 0)
            {
                dis[v] = dis[u] + 1;
                if (v == t)
                {
                    return true;
                }
                que.push(v);
            }
        }
    }
    return false;
}

int Dfs(int u, int t, int f)
{
    if (u == t)
    {
        return f;
    }
    int cost = 0;
    for (int i = head[u]; i != -1; i = edge[i].next)
    {
        int v = edge[i].to;
        int w = edge[i].w;
        if (dis[v] == dis[u] + 1 && w > 0)
        {
            int d = Dfs(v, t, min(w, f - cost));
            if (d > 0)
            {
                edge[i].w -= d;
                edge[i ^ 1].w += d;
                cost += d;
                if (cost == f)
                {
                    break;
                }
                else 
                {
                    dis[v] = -1;
                }
            }
        }
    }
    return cost;
}

int Dinic(int s, int t)
{
    int maxflow = 0;
    while (Bfs(s, t))
    {
        maxflow += Dfs(s, t, INF);
    }
    return maxflow;
}

int main(void)
{
    int n, f, d;
    while (scanf("%d %d %d", &n, &f, &d) != EOF)
    {
        Init();
        int i, j;
        int s = 0;
        int t = n * 2 + f + d + 1;
        for (i = 1; i <= f; i++)
        {
            int w;
            scanf("%d", &w);
            Addedge(s, i, w);
        }
        for (i = 1; i <= d; i++)
        {
            int w;
            scanf("%d", &w);
            Addedge(f + 2 * n + i, t, w);
        }
        for (i = 1; i <= n; i++)
        {
            Addedge(f + i, f + n + i, 1);
        }
        char str[MAXN];
        for (i = 1; i <= n; i++)
        {
            scanf("%s", &str[1]);
            for (j = 1; j <= f; j++)
            {
                if (str[j] == 'Y')
                {
                    Addedge(j, f + i, 1);
                }
            }
        }

        for (i = 1; i <= n; i++)
        {
            scanf("%s", &str[1]);
            for (j = 1; j <= d; j++)
            {
                if (str[j] == 'Y')
                {
                    Addedge(f + n + i, f + 2 * n + j, 1);
                }
            }
        }

        printf("%d\n", Dinic(s, t));
    }
    return 0;
}