首页 > 代码库 > hdu 4292 Food 最大流+拆点
hdu 4292 Food 最大流+拆点
Food
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2664 Accepted Submission(s): 899
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.
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).
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
F种食物,N个人,D种饮料
先输入一排F个数字的是每种食物的量;
再输入D个数字是每种饮料的量;
然后N行 是每个人可以接受的食物是哪几种,第一个Y代表可以接受第一种食物
再N行,是每个人可以接受的饮料是哪几种,
每个人都只用给他一个食物或者饮料
做法是, 设一个超级源点beg, beg 连接到 各种食物, 权值是该食物的量.
然后把每个人拆开, 拆成 点头 和点尾,因为只吃一个,所以权值是1;
然后把这各种食物,根据每个人的爱好连接 到 人的点头,因为只吃一个,所以权值是1
在把每个人的点尾根据个人爱好,连接到 饮料,权值同理也是1;
再设一个超级汇点fin, 把各种饮料连接到 fin;
像这样建图
#include<stdio.h> #include<string.h> #include<queue> using namespace std; #define inf 1000000 #define N 1000 #define M 100000 //N为点数 M为边数 200 400 200 inline int Min(int a,int b){return a>b?b:a;} //注意这个类型是int struct Edge{ int from, to, cap, nex; }edge[M*2];//双向边,注意RE 注意这个模版是 相同起末点的边 同时有效而不是去重 int head[N],edgenum;//2个要初始化-1和0 void init() { memset(head,-1,sizeof(head)); edgenum=0; } void addedge(int u, int v, int cap){//网络流要加反向弧 Edge E = {u, v, cap, head[u]}; edge[ edgenum ] = E; head[ u ] = edgenum++; Edge E2 = {v, u, 0, head[v]}; //这里的cap若是单向边要为0 edge[ edgenum ] = E2; head[ v ] = edgenum++; } int dis[N], cur[N];//dis[i]表示i点距离起点的距离 cur[i]表示i点所连接的边中 正在考虑的边 优化不再考虑已经用过的点 初始化为head bool vis[N]; bool BFS(int Start,int End){//跑一遍最短路 memset(vis,0,sizeof(vis)); memset(dis,-1,sizeof(dis)); queue<int>Q; Q.push(Start); dis[Start]=0; vis[Start]=1; while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i = head[u]; i != -1; i = edge[i].nex){ Edge E = edge[i]; if( !vis[E.to] && E.cap > 0) { vis[ E.to ] = true; dis[ E.to ] = dis[ u ] + 1; if(E.to == End) return true; Q.push( E.to ); } } } return false; } int DFS(int x, int a,int End){//当前 流入x 的流量是a 流量a 是所有流过边中 边权的最小值 if( x == End || a == 0)return a; int flow = 0, f; //flow表示从x点流到下面所有点,最大的流量 for(int& i = cur[x]; i != -1; i = edge[i].nex) { Edge& E = edge[i]; if(dis[x] + 1 == dis[E.to] && (f = DFS(E.to , Min(a, E.cap), End))>0 ) { E.cap -= f; edge[ i^1 ].cap += f;//反向边要减掉 flow += f; a -= f; if(a==0)break; } } return flow; } int Maxflow(int Start,int End){ int flow=0; while(BFS(Start,End)){ //当存在源点到汇点的路径时 memcpy(cur,head,sizeof(head));//把head的数组复制过去 flow += DFS(Start, inf, End); } return flow; } int main() { int fin,beg; int i,j,f,n,d,tem; char a[300]; while(scanf("%d%d%d",&n,&f,&d)!=EOF)//f个点代表食物, 2*n个点代表人 d个点代表饮料 { init(); fin=f+2*n+d+1; beg=0; for(i=1;i<=f;i++) { scanf("%d\n",&tem); addedge(beg, i , tem); } for(i=1;i<=d;i++) { scanf("%d\n",&tem); addedge(i+f+2*n, fin, tem); } for(i=1;i<=n;i++) { scanf("%s",a); for(j=0;j<f;j++) { if(a[j]=='Y') { addedge( j+1, f+i , 1);//食物到人 } } addedge(f+i, f+i+n, 1);//人的量 } for(i=1;i<=n;i++)//人 { scanf("%s",a); for(j=0;j<d;j++) { if(a[j]=='Y') { addedge(f+i+n, f+2*n+j+1,1);//人到饮料 } } } printf("%d\n",Maxflow(beg,fin)); } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。