HDU-4292 Food (maximum flow, split point)

Topic links: HDU-Food 4292

The meaning of problems

There are $ N $ individuals, $ F $ kinds of food, $ D $ kinds of drinks, food and beverages each have a certain amount each person needs to have a number 1 or no demand for each food and drink, asking $ F $ kinds of food and drink up to $ D $ types to meet the needs of individuals much.


Thinking

A man split into two nodes, divided into left and right point point unit, left point to the right edge of the Ministry of points connected capacity of 1, showing a person's contribution to the answer up to 1;

The food source to the representative node connected side, the number corresponding to the capacity of the food, the food to a human in need of such food left side portion connected point, a capacity of 1, 1 represents a demand;

Human right point portion connected to the beverage demand side, the capacity is 1, indicating a demand for the drink, the drink even sink side, the number corresponding to the capacity of the beverage, and then to run the maximum flow.


Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using std::queue;
const int INF = 0x3f3f3f3f, N = 1000, M = 200000;
int head[N], d[N];
int s, t, tot, maxflow;
struct Edge
{
    int to, cap, nex;
} edge[M];
queue<int> q;
void add(int x, int y, int z) {
    edge[++tot].to = y, edge[tot].cap = z, edge[tot].nex = head[x], head[x] = tot;
    edge[++tot].to = x, edge[tot].cap = 0, edge[tot].nex = head[y], head[y] = tot;
}
bool bfs() {
    memset(d, 0, sizeof(d));
    while (q.size()) q.pop();
    q.push(s); d[s] = 1;
    while (q.size()) {
        int x = q.front(); q.pop();
        for (int i = head[x]; i; i = edge[i].nex) {
            int v = edge[i].to;
            if (edge[i].cap && !d[v]) {
                q.push(v);
                d[v] = d[x] + 1;
                if (v == t) return true;
            }
        }
    }
    return false;
}
int dinic(int x, int flow) {
    if (x == t) return flow;
    int rest = flow, k;
    for (int i = head[x]; i && rest; i = edge[i].nex) {
        int v = edge[i].to;
        if (edge[i].cap && d[v] == d[x] + 1) {
            k = dinic(v, std::min(rest, edge[i].cap));
            if (!k) d[v] = 0;
            edge[i].cap -= k;
            edge[i^1].cap += k;
            rest -= k;
        }
    }
    return flow - rest;
}
void init(int v_num) {
    tot = 1, maxflow = 0;
    s = v_num, t = s + 1;
    memset(head, 0, sizeof(head));
}

int main() {
    int nn, nf, nd;
    while (~scanf("%d %d %d", &nn, &nf, &nd)) {
        init(nn * 2 + nf + nd);
        for (int i = 0, num; i < nf; i++) {
            scanf("%d", &num);
            add(s, i, num);
        }
        for (int i = 0, num; i < nd; i++) {
            scanf("%d", &num);
            add(i + nf, t, num);
        }
        char str[210];
        for (int i = 0; i < nn; i++) {
            scanf(" %s", str);
            for (int j = 0; j < nf; j++) {
                if (str[j] == 'Y') add(j, i + nf + nd, 1);
            }
            add(nf + nd + i, nf + nd + nn + i, 1);
        }
        for (int i = 0; i < nn; i++) {
            scanf(" %s", str);
            for (int j = 0; j < nd; j++) {
                if (str[j] == 'Y') add(nn + nf + nd + i, nf + j, 1);
            }
        }
        while (bfs()) maxflow += dinic(s, INF);
        printf("%d\n", maxflow);
    }
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/kangkang-/p/11331842.html