hdu-4292.food(类dining网络流建图)
Food
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 9289 Accepted Submission(s): 3019
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.
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).
1 1 1
1 1 1
YYN
NYY
YNY
YNY
YNY
YYN
YYN
NNY
/*
结点0 ~ n - 1存左牛结点
结点n ~ 2 * n - 1存右牛结点
结点2 * n ~ 2 * n + f - 1存左食物
结点2 * n + f ~ 2 * n + f * 2 - 1存右食物
结点2 * n + 2 * f ~ 2 * n + 2 * f + d - 1存饮料左
结点2 * n + 2 * f + d ~ 2 * n + 2 * f + d * 2 - 1存饮料右
结点2 * n + 2 * f + 2 * d为s,t = s = 1。
*/ #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + , maxm = * + , inf = 0x3f3f3f3f;
int numf[maxn], numd[maxn];
char str[maxn]; int tot, head[maxn << ], que[maxn << ], dep[maxn << ], cur[maxn << ], sta[maxn << ]; struct Edge {
int to, cap, flow, next, from;
} edge[maxm << ]; void init() {
tot = ;
memset(head, -, sizeof head);
} void addedge(int u, int v, int w) {
edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = ; edge[tot].from = u;
edge[tot].next = head[u]; head[u] = tot ++;
edge[tot].to = u; edge[tot].cap = ; edge[tot].flow = ; edge[tot].from = v;
edge[tot].next = head[v]; head[v] = tot ++;
} bool bfs(int s, int t, int n) {
memset(dep, -, sizeof dep[] * (n + ));
int front = , tail = ;
dep[s] = ;
que[tail ++] = s;
while(front < tail) {
int u = que[front ++];
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(edge[i].cap > edge[i].flow && dep[v] == -) {
dep[v] = dep[u] + ;
if(v == t) return true;
que[tail ++] = v;
}
}
}
return false;
} int dinic(int s, int t, int n) {
int maxflow = ;
while(bfs(s, t, n)) {
for(int i = ; i <= n; i ++) cur[i] = head[i];
int u = s, tail = ;
while(~cur[s]) {
if(u == t) {
int tp = inf;
for(int i = tail - ; i >= ; i --)
tp = min(tp, edge[sta[i]].cap - edge[sta[i]].flow);
maxflow += tp;
for(int i = tail - ; i >= ; i --) {
edge[sta[i]].flow += tp;
edge[sta[i] ^ ].flow -= tp;
if(edge[sta[i]].cap - edge[sta[i]].flow == ) tail = i;
}
u = edge[sta[tail] ^ ].to;
} else if(~ cur[u] && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + == dep[edge[cur[u]].to]) {
sta[tail ++] = cur[u];
u = edge[cur[u]].to;
} else {
while(u != s && cur[u] == -)
u = edge[sta[-- tail] ^ ].to;
cur[u] = edge[cur[u]].next;
}
}
}
return maxflow;
} int main() {
int n, f, d;
while(~scanf("%d %d %d", &n, &f, &d)) {
init();
int s = * n + * f + d * , t = s + ;//超级源点和超级汇点
for(int i = ; i < f; i ++) {
scanf("%d", &numf[i]);
addedge(s, * n + i, inf);//超级源点到食物左
addedge( * n + i, * n + f + i, numf[i]);//食物左到食物右
}
for(int i = ; i < d; i ++) {
scanf("%d", &numd[i]);
addedge( * n + * f + i, * n + * f + d + i, numd[i]);//饮料左到饮料右
addedge( * n + * f + d + i, t, inf);//饮料右到超级汇点
}
for(int i = ; i < n; i ++) {
addedge(i, n + i, );//左牛到右牛
}
for(int i = ; i < n; i++) {
scanf("%s", str);
for(int j = ; j < f; j ++) {
if(str[j] == 'Y')
addedge( * n + f + j, i, );//从食物右到左牛
}
}
for(int i = ; i < n; i ++) {
scanf("%s", str);
for(int j = ; j < d; j ++) {
if(str[j] == 'Y')
addedge(n + i, * n + * f + j, );//从右牛到左饮料
}
}
// for(int i = 2; i <= tot; i ++) {
// printf("%d -> %d\n", edge[i].from, edge[i].to);
// }
printf("%d\n", dinic(s, t, * n + * f + * d + ));
}
return ;
}
下面这种建图方法和上面的类似,只是上图是拆点限制点流量,而我们知道对于每一件食物,如果我们有一个人选取它,那么它必定是只选取了一件,因为后面拆点n决定的,那么也就是每个人只能取他所喜欢食物中的一种中的一个,所以我们只需要对我们能够提供的某种食物限量就可以了,也就是从源点到某种食物权值为food_num,这样就可以限制住每种食物的用量了,接着看饮料,如果某个人选取了一个饮料,那么他也只能选取这一种饮料中的一瓶,因为前面已经对n拆点导致它能扩展的流也只有1,所以导致她选的饮料也是1对1,所以想要限制饮料的个数,也只需要无限索取,直到最后无法流到汇点就ok,那也就是从饮料到汇点权值为drink_num。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + , maxm = * + , inf = 0x3f3f3f3f;
int numf[maxn], numd[maxn];
char str[maxn]; int tot, head[maxn << ], que[maxn << ], dep[maxn << ], cur[maxn << ], sta[maxn << ]; struct Edge {
int to, cap, flow, next, from;
} edge[maxm << ]; void init() {
tot = ;
memset(head, -, sizeof head);
} void addedge(int u, int v, int w) {
edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = ; edge[tot].from = u;
edge[tot].next = head[u]; head[u] = tot ++;
edge[tot].to = u; edge[tot].cap = ; edge[tot].flow = ; edge[tot].from = v;
edge[tot].next = head[v]; head[v] = tot ++;
} bool bfs(int s, int t, int n) {
memset(dep, -, sizeof dep[] * (n + ));
int front = , tail = ;
dep[s] = ;
que[tail ++] = s;
while(front < tail) {
int u = que[front ++];
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(edge[i].cap > edge[i].flow && dep[v] == -) {
dep[v] = dep[u] + ;
if(v == t) return true;
que[tail ++] = v;
}
}
}
return false;
} int dinic(int s, int t, int n) {
int maxflow = ;
while(bfs(s, t, n)) {
for(int i = ; i <= n; i ++) cur[i] = head[i];
int u = s, tail = ;
while(~cur[s]) {
if(u == t) {
int tp = inf;
for(int i = tail - ; i >= ; i --)
tp = min(tp, edge[sta[i]].cap - edge[sta[i]].flow);
maxflow += tp;
for(int i = tail - ; i >= ; i --) {
edge[sta[i]].flow += tp;
edge[sta[i] ^ ].flow -= tp;
if(edge[sta[i]].cap - edge[sta[i]].flow == ) tail = i;
}
u = edge[sta[tail] ^ ].to;
} else if(~ cur[u] && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + == dep[edge[cur[u]].to]) {
sta[tail ++] = cur[u];
u = edge[cur[u]].to;
} else {
while(u != s && cur[u] == -)
u = edge[sta[-- tail] ^ ].to;
cur[u] = edge[cur[u]].next;
}
}
}
return maxflow;
} int main() {
int n, f, d;
while(~scanf("%d %d %d", &n, &f, &d)) {
init();
int s = * n + f + d, t = s + ;//超级源点和超级汇点
for(int i = ; i < f; i ++) {
scanf("%d", &numf[i]);
addedge(s, n * + i, numf[i]);
}
for(int i = ; i < d; i ++) {
scanf("%d", &numd[i]);
addedge(n * + f + i, t, numd[i]);
}
for(int i = ; i < n; i++) {
addedge(i, n + i, );//左牛到右牛
scanf("%s", str);
for(int j = ; j < f; j ++) {
if(str[j] == 'Y')
addedge( * n + j, i, );
}
}
for(int i = ; i < n; i ++) {
scanf("%s", str);
for(int j = ; j < d; j ++) {
if(str[j] == 'Y')
addedge(n + i, * n + f + j, );//从右牛到饮料
}
}
// for(int i = 2; i <= tot; i ++) {
// printf("%d -> %d\n", edge[i].from, edge[i].to);
// }
printf("%d\n", dinic(s, t, * n + f + d + ));
}
return ;
}
不得不承认这种做法确实节省了很多空间呀。
hdu-4292.food(类dining网络流建图)的更多相关文章
- HDU 4888 Redraw Beautiful Drawings 网络流 建图
题意: 给定n, m, k 以下n个整数 a[n] 以下m个整数 b[n] 用数字[0,k]构造一个n*m的矩阵 若有唯一解则输出这个矩阵.若有多解输出Not Unique,若无解输出Impossib ...
- hdu 5294 Tricks Device 最短路建图+最小割
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5294 Tricks Device Time Limit: 2000/1000 MS (Java/Other ...
- joj 2453 candy 网络流建图的题
Problem D: Candy As a teacher of a kindergarten, you have many things to do during a day, one of whi ...
- [ZJOI2010]贪吃的老鼠(网络流+建图)
题目描述 奶酪店里最近出现了m只老鼠!它们的目标就是把生产出来的所有奶酪都吃掉.奶酪店中一天会生产n块奶酪,其中第i块的大小为pi,会在第ri秒被生产出来,并且必须在第di秒之前将它吃掉.第j只老鼠吃 ...
- hdu 2647 (拓扑排序 邻接表建图的模板) Reward
题目链接http://acm.hdu.edu.cn/showproblem.php?pid=2647 老板给员工发工资,每个人的基本工资都是888,然后还有奖金,然后员工之间有矛盾,有的员工希望比某员 ...
- 网络流建图(典型)(EK)
题目链接:https://cn.vjudge.net/contest/68128#problem/B 具体思路: 按照 源点 - > 食物 - > 牛1 - > 牛2 - > ...
- hdu 4857 逃生 拓扑排序+逆向建图
逃生 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Descr ...
- HDU 4444:Walk(思维建图+BFS)***
http://acm.hdu.edu.cn/showproblem.php?pid=4444 题意:给出一个起点一个终点,给出n个矩形的两个对立顶点,问最少需要拐多少次弯可以从起点到达终点,如果不能输 ...
- URAL 1736 Chinese Hockey 网络流+建图
题目链接:点击打开链接 题意: 给定n个队伍的得分情况,输出随意一个可行解. n个队伍随意2个队伍 a, b 间有且仅有一场比赛. 比赛结果分4种: 1.a +3, b +0 2.a +0, b +3 ...
随机推荐
- java Thread源码分析
一.使用 java 多线程 java多线程其中两种使用方式: 1.继承 Thread 类 2.实现 Runnable 接口 public class ThreadTest { public stati ...
- java初学第一天
public class HellowWorld{ public static void main(String[] args){ System.out.println("jiuxu&quo ...
- SQL插入字段
//SQL插入字段 String dropTable="drop table if exists test;"; String columnGid ="alter tab ...
- 用PL/SQL登录显示 “无法解析指定标识符”
错误现象: 为了看表空间是否完整建好,打开相应的连接工具plsql,但是打不开,显示 “无法解析指定标识符”: 处理方式: 首先点击取消直接登录,打开工具---->首选项,在路径上看指定好没有 ...
- iOS---如何获取手机的本地照片和相册
__weak ViewController *weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIO ...
- word的公式编辑器在插入对象里面!!!!!!!!!!!!!
word的公式编辑器在 插入->对象 里面!!!!!!!!!!!!!
- layer.confirm
layer.confirm('确定不选择花车?', { title: false, btn: ['确定','取消'] //按钮 }, function(ind){ layer.close(ind); ...
- 微信小程序支付 java
原文:https://blog.csdn.net/zhourenfei17/article/details/77765585 话不多说,直接开撸. 支付流程步骤: 1)首先调用wx.login方法获取 ...
- tomcat安全配置参考
0x01 基本配置 1 删除默认目录 安装完tomcat后,删除$CATALINA_HOME/webapps下默认的所有目录文件 rm -rf /srv/apache-tomcat/webapps/ ...
- Java数据结构之单链表
这篇文章主要讲解了通过java实现单链表的操作,一般我们开始学习链表的时候,都是使用C语言,C语言中我们可以通过结构体来定义节点,但是在Java中,我们没有结构体,我们使用的是通过类来定义我们所需要的 ...