HDU - 4292【最大流_拆点_建图】

Food


题意:

  • n n 个人,有 f f 种食物, d d 种饮料,问能拿到自己钟意的食物和饮料的人最多有多少?

思路

  • s f o o d p e o p l e 1 p e o p l e 2 d r i n k t s - food - people1 - people2 - drink - t p e o p l e 1 people1 p e o p l e 2 people2 是一个人拆成两个点,两者中间的边权值为 1 1
  • s f o o d s - food 边权是每种食物的数量
  • d r i n k t drink - t 边权是每种饮料的数量
  • f o o d p e o p l e 1 food - people1 p e o p l e 2 d r i n k people2 - drink 若存在边,则说明这个人喜欢对应食物或者饮料,边权为 1 1

跑最大流即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
inline int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -f; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}

const int maxN = 1000;
const int maxM = 200000;

struct EDGE{
    int adj, to, w;
    EDGE(int a = -1, int b = 0, int c = 0): adj(a), to(b), w(c) {}
}edge[maxM];
int head[maxN], cur[maxN], cnt;
void init()
{
    memset(head, -1, sizeof(head));
    cnt = 0;
}

void add_edge(int u, int v, int w)
{
    edge[cnt] = EDGE(head[u], v, w);
    head[u] = cnt ++ ;
}

int n, f, d, s, t;
int food, drink;
int deep[maxN];

bool bfs()
{
    for(int i = 0; i <= f + d + n + n + 2; ++ i )
        deep[i] = 0, cur[i] = head[i];
    queue<int>q;
    q.push(s); deep[s] = 1;
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        for(int i = head[u]; ~i; i = edge[i].adj)
        {
            int v = edge[i].to;
            if(!deep[v] && edge[i].w)
            {
                deep[v] = deep[u] + 1;
                q.push(v);
            }
        }
    }
    return deep[t];
}

int dfs(int u, int flow)
{
    if(u == t || !flow) return flow;
    for(int &i = cur[u]; ~i; i = edge[i].adj)
    {
        int v = edge[i].to;
        if(deep[v] == deep[u] + 1 && edge[i].w)
        {
            if(int newFlow = dfs(v, min(flow, edge[i].w)))
            {
                edge[i].w -= newFlow;
                edge[i ^ 1].w += newFlow;
                return newFlow;
            }
        }
    }
    return 0;
}

int dinic()
{
    int maxFlow = 0;
    while(bfs())
    {
        while(int newFlow = dfs(s, INF))
            maxFlow += newFlow;
    }
    return maxFlow;
}

int main()
{
    while(~scanf("%d%d%d", &n, &f, &d))
    {
        init();
        s = f + d + n + n + 1;
        t = s + 1;
        //food[1, f]
        //drink[f + 1, f + d]
        //people1[f + d + 1, f + d + n]
        //people2[f + d + n + 1, f + d + n + n]
        for(int i = 1; i <= f; ++ i )
            food = read(), add_edge(s, i, food), add_edge(i, s, 0); // s-food
        for(int i = 1; i <= d; ++ i )
            drink = read(), add_edge(f + i, t, drink), add_edge(t, f + i, 0); // drink-t
        for(int i = 1; i <= n; ++ i )
            add_edge(f + d + i, f + d + n + i, 1), add_edge(f + d + n + i, f + d + i, 0); // p-p
        for(int i = 1; i <= n; ++ i ) //people
        {
            char str[205]; cin.getline(str, sizeof(str));
            for(int j = 0; j < f; ++ j )
                if(str[j] == 'Y')
                    add_edge(j + 1, f + d + i, 1), // food - people1
                            add_edge(f + d + i, j + 1, 0);
        }
        for(int i = 1; i <= n; ++ i )
        {
            char str[205]; cin.getline(str, sizeof(str));
            for(int j = 0; j < d; ++ j )
                if(str[j] == 'Y')
                    add_edge(f + d + n + i, f + j + 1, 1), // people2 - drink
                            add_edge(f + j + 1, f + d + n + i, 0);
        }
        printf("%d\n", dinic());
    }
    return 0;
}
发布了273 篇原创文章 · 获赞 76 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/104824964