题意:给定每个人所喜欢的食物和饮料种类以及每种食物和饮料的数量,一个人需要一种食物和一种饮料(数量为1即可),问最多满足多少人的需要

思路:由于食物和饮料对于人来说需要同时满足,它们是“与”的关系,所以建模时需要放在不同的层,另外如果把人放在根,食物和饮料依次放后面,则每个人会扩展出f*d个节点出来,边数有f*d条,而如果把人放中间,类似于“双向广搜”的原理,层数减半,边数大大减少。具体来说,从源点向每种食物连边,容量为其数量,如果某个人喜欢某种食物,则从食物向人连边,容量为1,为了限制人只能选择一个食物和饮料,需要人为地加n个新节点与每个人一一对应,从人向其所对应的新节点连一条容量为1的边,然后向喜欢的饮料各连一条容量为1的边,最后连回汇点,容量为饮料数量。图如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/* ******************************************************************************** */
#include <iostream>                                                                 //
#include <cstdio>                                                                   //
#include <cmath>                                                                    //
#include <cstdlib>                                                                  //
#include <cstring>                                                                  //
#include <vector>                                                                   //
#include <ctime>                                                                    //
#include <deque>                                                                    //
#include <queue>                                                                    //
#include <algorithm>                                                                //
#include <map>                                                                      //
using namespace std;                                                                //
                                                                                    //
#define pb push_back                                                                //
#define mp make_pair                                                                //
#define X first                                                                     //
#define Y second                                                                    //
#define all(a) (a).begin(), (a).end()                                               //
#define foreach(a, i) for (typeof(a.begin()) i = a.begin(); i != a.end(); ++ i)     //
#define fill(a, x) memset(a, x, sizeof(a))                                          //
                                                                                    //
void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}    //
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>                    //
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;          //
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>      //
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>              //
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>   //
void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}   //
                                                                                    //
typedef pair<intint> pii;                                                         //
typedef long long ll;                                                               //
typedef unsigned long long ull;                                                     //
                                                                                    //
template<typename T>bool umax(T&a, const T&b){return b>a?false:(a=b,true);}         //
template<typename T>bool umin(T&a, const T&b){return b<a?false:(a=b,true);}         //
template<typename T>                                                                //
void V2A(T a[],const vector<T>&b){for(int i=0;i<b.size();i++)a[i]=b[i];}            //
template<typename T>                                                                //
void A2V(vector<T>&a,const T b[]){for(int i=0;i<a.size();i++)a[i]=b[i];}            //
                                                                                    //
/* -------------------------------------------------------------------------------- */
 
 
struct Dinic {
private:
    const static int maxn = 800 + 7;
    struct Edge {
        int from, to, cap;
        Edge(int u, int v, int w): from(u), to(v), cap(w) {}
    };
    int s, t;
    vector<Edge> edges;
    vector<int> G[maxn];
    bool vis[maxn];
    int d[maxn], cur[maxn];
 
    bool bfs() {
        memset(vis, 0, sizeof(vis));
        queue<int> Q;
        Q.push(s);
        d[s] = 0;
        vis[s] = true;
        while (!Q.empty()) {
            int x = Q.front(); Q.pop();
            for (int i = 0; i < G[x].size(); i ++) {
                Edge &e = edges[G[x][i]];
                if (!vis[e.to] && e.cap) {
                    vis[e.to] = true;
                    d[e.to] = d[x] + 1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    int dfs(int x, int a) {
        if (x == t || a == 0) return a;
        int flow = 0, f;
        for (int &i = cur[x]; i < G[x].size(); i ++) {
            Edge &e = edges[G[x][i]];
            if (d[x] + 1 == d[e.to] && (f = dfs(e.to, min(a, e.cap))) > 0) {
                e.cap -= f;
                edges[G[x][i] ^ 1].cap += f;
                flow += f;
                a -= f;
                if (a == 0) break;
            }
        }
        return flow;
    }
 
public:
    void clear() {
        for (int i = 0; i < maxn; i ++) G[i].clear();
        edges.clear();
        memset(d, 0, sizeof(d));
    }
    void add(int from, int to, int cap) {
        edges.push_back(Edge(from, to, cap));
        edges.push_back(Edge(to, from, 0));
        int m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    }
 
    int solve(int s, int t) {
        this->s = s; this->t = t;
        int flow = 0;
        while (bfs()) {
            memset(cur, 0, sizeof(cur));
            flow += dfs(s, 1e9);
        }
        return flow;
    }
 
};
Dinic solver;
const int maxn = 207;
int cf[maxn], cd[maxn];
bool likef[maxn][maxn], liked[maxn][maxn];
 
int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt""r", stdin);
#endif // ONLINE_JUDGE
    int n, f, d;
    while (cin >> n >> f >> d) {
        RI(cf + 1, cf + 1 + f);
        RI(cd + 1, cd + 1 + d);
        for (int i = 1; i <= n; i ++) {
            char s[234];
            scanf("%s", s);
            for (int j = 0; j < f; j ++) {
                likef[i][j + 1] = s[j] == 'Y';
            }
        }
        for (int i = 1; i <= n; i ++) {
            char s[234];
            scanf("%s", s);
            for (int j = 0; j < d; j ++) {
                liked[i][j + 1] = s[j] == 'Y';
            }
        }
        solver.clear();
        for (int i = 1; i <= f; i ++) {
            solver.add(0, i, cf[i]);
        }
        for (int i = 1; i <= n; i ++) {
            for (int j = 1; j <= f; j ++) {
                if (likef[i][j]) solver.add(j, f + i, 1);
            }
        }
        for (int i = 1; i <= n; i ++) {
            solver.add(f + i, f + n + i, 1);
        }
        for (int i = 1; i <= n; i ++) {
            for (int j = 1; j <= d; j ++) {
                if (liked[i][j]) solver.add(f + n + i, f + n + n + j, 1);
            }
        }
        for (int i = 1; i <= d; i ++) {
            solver.add(f + n + n + i, f + n + n + d + 1, cd[i]);
        }
        cout << solver.solve(0, f + n + n + d + 1) << endl;
    }
    return 0;                                                                       //
}                                                                                   //
                                                                                    //
                                                                                    //
                                                                                    //
/* ******************************************************************************** */

[hdu4292]最大流,拆点的更多相关文章

  1. poj 3498 March of the Penguins(最大流+拆点)

    题目大意:在南极生活着一些企鹅,这些企鹅站在一些冰块上,现在要让这些企鹅都跳到同一个冰块上.但是企鹅有最大的跳跃距离,每只企鹅从冰块上跳走时会给冰块造成损害,因此企鹅跳离每个冰块都有次数限制.找出企鹅 ...

  2. poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分, dinic, isap

    poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分 dinic /* * Author: yew1eb * Created Time: 2014年10月31日 星期五 ...

  3. HDU4292 Food —— 最大流 + 拆点

    题目链接:https://vjudge.net/problem/HDU-4292 Food Time Limit: 2000/1000 MS (Java/Others)    Memory Limit ...

  4. hdu4289 最小割最大流 (拆点最大流)

    最小割最大流定理:(参考刘汝佳p369)增广路算法结束时,令已标号结点(a[u]>0的结点)集合为S,其他结点集合为T=V-S,则(S,T)是图的s-t最小割. Problem Descript ...

  5. BZOJ-1877 晨跑 最小费用最大流+拆点

    其实我是不想做这种水题的QWQ,没办法,剧情需要 1877: [SDOI2009]晨跑 Time Limit: 4 Sec Memory Limit: 64 MB Submit: 1704 Solve ...

  6. BZOJ-1070 修车 最小费用最大流+拆点+略坑建图

    1070: [SCOI2007]修车 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 3624 Solved: 1452 [Submit][Status] ...

  7. hdu 4289 最大流拆点

    大致题意:     给出一个又n个点,m条边组成的无向图.给出两个点s,t.对于图中的每个点,去掉这个点都需要一定的花费.求至少多少花费才能使得s和t之间不连通. 大致思路:     最基础的拆点最大 ...

  8. 洛谷 P2764 最小路径覆盖问题【最大流+拆点+路径输出】

    题目链接:https://www.luogu.org/problemnew/show/P2764 题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V ...

  9. UVA-11613 Acme Corporation (最大费用最大流+拆点)

    题目大意:有一种商品X,其每每单位存放一个月的代价I固定.并且已知其每月的最大生产量.生产每单位的的代价.最大销售量和销售单价,还已知每个月生产的X能最多能存放的时间(以月为单位).问只考虑前m个月, ...

随机推荐

  1. C - Ekka Dokka

    Ekka and his friend Dokka decided to buy a cake. They both love cakes and that's why they want to sh ...

  2. idea创建springboot工程,总出现响应超时问题,或者无法连接http://start.spring.io导致创建失败

    问题描述如下: idea创建springboot工程,总出现响应超时问题,或者无法连接http://start.spring.io导致创建失败 从我出现此类问题几次的解决方案 依照解决效率分为一下三种 ...

  3. Java数组 —— 八大排序

    (请观看本人博文--<详解 普通数组 -- Arrays类 与 浅克隆>) 在本人<数据结构与算法>专栏的讲解中,本人讲解了如何去实现数组的八大排序. 但是,在讲解的过程中,我 ...

  4. Aria2任意文件写入漏洞

    目录: 简介 漏洞描述 payload 漏洞复现 一.Aria2介绍 Aria2是一个命令行下运行,多协议,多来源下载工具(HTTP / HTTPS,FTP,BitTorrent,Metalink), ...

  5. [Java网络安全系列面试题] GET 和 POST 的区别在哪里?

    一. 概述 本文的内容源自其他博客的总结,属于笔者的读书笔记,结构如下: HTTP 的请求报文 GET 方法的特点 POST 方法的特点 GET 和 POST 的区别 二. HTTP 的请求报文 首先 ...

  6. IOC趣味理解

    假设一个场景:   假设你是一个四岁孩子,饿了,想吃东西.怎么做? 1,哪有吃的去哪拿,你知道冰箱有吃的,你去冰箱拿〉会有风险.比如,拿了生的吃的,吃坏肚子,甚至拿了不能吃的东西. 2, 找父母(IO ...

  7. 如何快速地恢复你的win10

    win10清单 这份List不会介绍如何安装系统,而是当面对一个新系统,如何最快的搭建,或者说恢复到一个生产力环境. 必备习惯 备份软件安装包和常用内容上云是高效恢复的两点关键. 备份软件安装包 我的 ...

  8. apache虚拟主机配置-域名/IP和端口两种配置

    由于百度上有非常详细的资料,我这里就转载而已:https://jingyan.baidu.com/article/4f7d5712d48a191a201927e0.html

  9. python学习02python入门二

    学前须知:1.本文档有关内容均建立在python3.x版本上,python2.x已经成为历史,如有需要,文内会特别说明. 2.本文使用的编辑器多为架构在Windows上的pycharm,如需了解Lin ...

  10. (第二篇)shell的简单了解

    Shell (类似开发工具) Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程 ...