hdu4292——Food(SAP+拆点)
来源:互联网 发布:newsql数据库有哪些 编辑:程序博客网 时间:2024/06/13 09:41
Problem Description
You, a part-time dining service worker in your college’s dining hall, are now confused with a new problem: serve as many people as possible.
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.
Input
There are several test cases.
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).
Output
For each test case, please print a single line with one integer, the maximum number of people to be satisfied.
Sample Input
4 3 3
1 1 1
1 1 1
YYN
NYY
YNY
YNY
YNY
YYN
YYN
NNY
Sample Output
3
这题原理上和poj3281很相似,我用刚学的SAP模板套了一遍,发现以下几个问题(不敢相信我居然能发现):
n是所有的点的个数,理论上n=des+1就行;
点的个数MAXN和边的个数很玄学,以我的知识水平不知道它们之间应该有什么样的关系,总之一开始边数是点数的4倍,WA,改成32倍就过了。
#include <iostream>#include <cstring>#include <string>#include <vector>#include <queue>#include <cstdio>#include <set>#include <cmath>#include <map>#include <algorithm>#define INF 0x3f3f3f3f#define MAXN 11000#define Mod 10001using namespace std;struct E{ int to, frm, nxt, cap;}edge[MAXN<<5];int head[MAXN], e, n, m, src, des;int dep[MAXN], gap[MAXN]; //gap[x]=y:说明残留网络中dep[i]=x的个数为yvoid addedge(int u, int v, int c){ edge[e].frm = u; edge[e].to = v; edge[e].cap = c; edge[e].nxt = head[u]; head[u] = e++; edge[e].frm = v; edge[e].to = u; edge[e].cap = 0; edge[e].nxt = head[v]; head[v] = e++;}int Q[MAXN];void BFS(int src, int des){ memset(dep, -1, sizeof(dep)); memset(gap, 0, sizeof(gap)); gap[0] = 1; //说明此时有1个dep[i] = 0 int front = 0, rear = 0; dep[des] = 0; Q[rear++] = des; int u, v; while (front != rear) { u = Q[front++]; //cout<<u<<endl; front = front%MAXN; for (int i=head[u]; i!=-1; i=edge[i].nxt) { //cout<<i<<endl; v = edge[i].to; if (edge[i].cap != 0 || dep[v] != -1) continue; Q[rear++] = v; rear = rear % MAXN; ++gap[dep[v] = dep[u] + 1]; //求出各层次的数量 } }}int S[MAXN],cur[MAXN];int SAP(){ int res = 0; BFS(src, des); int top = 0; memcpy(cur, head, sizeof(head)); int u = src, i; while (dep[src] < n) //n为结点的个数 { if (u == des) { int temp = INF, inser = n; for (i=0; i!=top; ++i) if (temp > edge[S[i]].cap) { temp = edge[S[i]].cap; inser = i; } for (i=0; i!=top; ++i) { edge[S[i]].cap -= temp; edge[S[i]^1].cap += temp; } res += temp; top = inser; u = edge[S[top]].frm; } if (u != des && gap[dep[u] -1] == 0)//出现断层,无增广路 break; for (i = cur[u]; i != -1; i = edge[i].nxt)//遍历与u相连的未遍历结点 if (edge[i].cap != 0 && dep[u] == dep[edge[i].to] + 1) //层序关系, 找到允许 break; if (i != -1)//找到允许弧 { cur[u] = i; S[top++] = i;//加入路径栈 u = edge[i].to;//查找下一个结点 } else //无允许的路径,修改标号 当前点的标号比与之相连的点中最小的多1 { int min = n; for (i = head[u]; i != -1; i = edge[i].nxt) //找到与u相连的v中dep[v]最小的点 { if (edge[i].cap == 0) continue; if (min > dep[edge[i].to]) { min = dep[edge[i].to]; cur[u] = i; //最小标号就是最新的允许弧 } } --gap[dep[u]]; //dep[u] 的个数变化了 所以修改gap ++gap[dep[u] = min + 1]; //将dep[u]设为min(dep[v]) + 1, 同时修改相应的gap[] if (u != src) //该点非源点&&以u开始的允许弧不存在,退点 u = edge[S[--top]].frm; } } return res;}int main(){ int N,D,F,w; while(~scanf("%d%d%d",&N,&F,&D)) { //1~F,F+1~F+N,F+N+1~F+N+N,F+N+N+1~F+N+N+D src=0; des=F+N+N+D+1; n=des+1; //还有源点,汇点 e=0; memset(head,-1,sizeof(head)); for(int i=1;i<=F;++i) { scanf("%d",&w); addedge(src,i,w); } for(int i=1;i<=D;++i) { scanf("%d",&w); addedge(F+N+N+i,des,w); } for(int i=1;i<=N;++i) { addedge(F+i,F+N+i,1); } string op; for(int i=1;i<=N;++i) { cin>>op; for(int j=0;j<F;++j) { if(op[j]=='Y') { addedge(j+1,F+i,1); } } } for(int i=1;i<=N;++i) { cin>>op; for(int j=0;j<D;++j) { if(op[j]=='Y') { addedge(F+N+i,F+N+N+j+1,1); } } } int ans=SAP(); printf("%d\n",ans); } return 0;}
- hdu4292——Food(SAP+拆点)
- HDU4292--Food拆点网络流
- hdu4292 Food 网络最大流 拆点
- HDU4292--Food
- HDU4292--Food
- hdu4292 food
- HDU 4292 —— Food(最大流,拆点)
- hdu4292 Food (ISAP算法)
- hdu4292 Food --- 最大流
- (最大流)HDU4292 Food
- 解题报告 之 HDU4292 Food
- HDU4292 Food(基础最大流)
- hdu4292 网络流 —最大流
- HDU 4292 Food(最小割,人数拆点)
- 2010成都赛区网络赛第五题---Food(hdu4292)
- HDU 4292 Food(拆点,最大流)
- hdu 4292 Food 最大流+拆点
- hdu 4292 Food isap+拆点
- weka连接mysql
- java : Iterator Pattern
- Android创建原图的副本
- 非root下,如何将android中的数据库文件存放到外部存储并导出
- 学习classList写的小Demo
- hdu4292——Food(SAP+拆点)
- jQuery内容过滤选择器
- 海洋CMS6.28命令执行漏洞
- 洛谷 P1134 阶乘问题
- 专题:计算几何学 (多边形的中心) hdu1115Lifting the Stone
- getContextPath、getServletPath、getRequestURI、getRealPath、getRequestURL、的区别
- Stockbroker Grapevine
- could not get lock /var/lib/dpkg/lock -open
- C#中的抽象类的特征