HDU 4292 最大流

HDU 4292
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4292
题意:
n个人,F种食物,L种饮料。
一个人需要喝一种饮料一种食物,他对食物和饮料有多种选择。
食物有限,饮料也有限。
问最多同时满足多少个人的要求。
思路:
最大流。
起点到食物,容量为食物数量。
食物到人,如果人可以选择这种食物,容量为1.
人到人,一个人裂成两个点,一个点指向另一个点,容量为1.
人到饮料,饮料到汇点,类似。

源码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
#include <vector>
using namespace std;
#define inf (1000000000)
const int MAXN = 200 * 4 + 5;
int head[MAXN], cnt;
struct Edge
{
    int u, v;
    int flow, ne;
    Edge(){}
    Edge(int _u, int _v, int _flow){u = _u, v = _v, flow = _flow, ne = head[u];}
}edge[MAXN*MAXN];
void add_edge(int u, int v, int flow)
{
    edge[cnt] = Edge(u, v, flow);
    head[u] = cnt++;
    edge[cnt] = Edge(v, u, 0);
    head[v] = cnt++;
}
int d[MAXN], p[MAXN], num[MAXN], vis[MAXN];
queue<int>que;
void BFS(int t)
{
    while(!que.empty()) que.pop();
    memset(vis, 0, sizeof(vis));
    memset(num, 0, sizeof(num));
    que.push(t), d[t] = 0, vis[t] = 1;
    while(!que.empty()){
        int u = que.front();    que.pop();
        num[d[u]]++;
        for(int now = head[u] ; now != -1 ; now = edge[now].ne){
            int v = edge[now].v;
            if(vis[v] == 0) vis[v] = 1, d[v] = d[u] + 1, que.push(v);
        }
    }
}
int Augment(int s, int t)
{
    int flow = inf;
    int u = t;
    while(u != s){
        flow = min(flow, edge[p[u]].flow);
        u = edge[p[u]].u;
    }
    u = t;
    while(u != s){
        edge[p[u]].flow -= flow;
        edge[p[u]^1].flow += flow;
        u = edge[p[u]].u;
    }
    return flow;
}
int cur[MAXN];
int ISAP(int s, int t, int n)
{
    BFS(t);
    for(int i = 0 ; i <= n ; i++)
        cur[i] = head[i];
    int flow = 0;
    int u = s;
    while(d[s] < n + 1){
// printf("u = %d\n", u);
// system("pause");
        if(u == t){
            flow += Augment(s, t);
            u = s;
        }
        int ok = 0;
        for(int now = cur[u] ; now != -1 ; now = edge[now].ne){
            int v = edge[now].v;
            if(edge[now].flow && d[v] == d[u] - 1){
                cur[u] = now;
                p[v] = now;
                u = v;
                ok = 1; break;
            }
        }
        if(!ok){
            int ts = n;
            for(int now = head[u] ; now != -1 ; now = edge[now].ne){
                if(edge[now].flow)  ts = min(ts, d[edge[now].v]);
            }
            if(--num[d[u]] == 0)    break;
            cur[u] = head[u];
            num[d[u] = ts + 1]++;
            if(u != s)  u = edge[p[u]].u;
        }
    }
    return flow;
}
char str[MAXN];
int main()
{
    int n, m, l;
    while(scanf("%d%d%d", &n, &m, &l) != EOF)
    {
        memset(head, -1, sizeof(head));
        cnt = 0;
        int s = 0, t = 2 * n + m + l + 1;
        int val;
        for(int i = 1 ; i <= n ; i++)
            add_edge(m + i, m + n + i, 1);
        for(int i = 1 ; i <= m ; i++){
            scanf("%d", &val);
            add_edge(s, i, val);
        }
        for(int i = 1 ; i <= l ; i++){
            scanf("%d", &val);
            add_edge(i + 2 * n + m, t, val);
        }
        for(int i = 1 ; i <= n ; i++){
            scanf("%s", str);
            for(int j = 0 ; j < m ; j++){
                if(str[j] == 'Y')
                    add_edge(j + 1, m + i, 1);
            }
        }
        for(int i = 1 ; i <= n ; i++){
            scanf("%s", str);
            for(int j = 0 ; j < l ; j++){
                if(str[j] == 'Y')
                    add_edge(m + n + i, m + 2 * n + j + 1, 1);
            }
        }
        int ans = ISAP(s, t, m + 2 * n + l);
        printf("%d\n", ans);
    }
    return 0;
}

你可能感兴趣的:(HDU 4292 最大流)