您的位置:首页 > 理论基础 > 计算机网络

HDU 4292 Food 网络流最大流 拆点

2016-05-13 09:21 666 查看
在使用网络流之前,最重要的一件事就是构造流量图,必须保证从源点到汇点的一条路径是一个可行解才行。

对于这道题目,由于每个人既要吃饭,还要喝饮料,因此就不能把一个人当成“一”个人看待,因为如果看成一个人,那么无论怎么建图,都无法保证从源到汇的路径是可行解,这时候我们就需要将一个人拆成两个,一个负责吃饭,一个负责喝饮料,然后再让吃饭的人指向喝饮料的人,容量为1。最后在建立食物与人的边喝人与饮料的边,说起来比较抽象,见下图。


Problem - 4292

Food

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4534    Accepted Submission(s): 1533

[align=left]Problem Description[/align]
  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.

[align=left]Input[/align]
  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).

[align=left]Output[/align]
  For each test case, please print a single line with one integer, the maximum number of people to be satisfied.

[align=left]Sample Input[/align]

4 3 3 1 1 1 1 1 1 YYN NYY YNY YNY YNY YYN YYN NNY

[align=left]Sample Output[/align]

3

[align=left]Source[/align]
2012 ACM/ICPC Asia Regional Chengdu Online
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

const int MAXN=10001;
const int MAXM=4000100;
const int INF=99999999;
struct Edge
{
int to,next,cap,flow;
};

Edge edge[MAXM];
int head[MAXN],tol;
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];
int N,F,D;

int num;

void init()
{
tol=0;
memset(head,-1,sizeof(head));
}

void addedge(int u,int v,int w,int rw=0)
{
edge[tol].to=v;
edge[tol].cap=w;
edge[tol].next=head[u];
edge[tol].flow=0;
head[u]=tol++;
edge[tol].to=u;
edge[tol].cap=rw;
edge[tol].next=head[v];
edge[tol].flow=0;
head[v]=tol++;
}

int sap(int start,int end,int N)
{
memset(gap,0,sizeof(gap));
memset(dep,0,sizeof(dep));
memcpy(cur,head,sizeof(head));
int u=start;
pre[u]=-1;
gap[0]=N;
int ans=0;
while(dep[start]<N)
{
if(u==end)
{
int Min=INF;
for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
if(Min>edge[i].cap-edge[i].flow)
Min=edge[i].cap-edge[i].flow;
for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
{
edge[i].flow+=Min;
edge[i^1].flow-=Min;
}
u=start;
ans+=Min;
continue;
}
bool flag=false;
int v;
for(int i=cur[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u])
{
flag=true;
cur[u]=pre[v]=i;
break;
}
}
if(flag)
{
u=v;
continue;
}
int Min=N;
for(int i=head[u];i!=-1;i=edge[i].next)
if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min)
{
Min=dep[edge[i].to];
cur[u]=i;
}
gap[dep[u]]--;
if(!gap[dep[u]])
return ans;
dep[u]=Min+1;
gap[dep[u]]++;
if(u!=start)
u=edge[pre[u]^1].to;
}
return ans;
}

int main()
{
int source,sink;
int ans;
string req;
while(~scanf("%d%d%d",&N,&F,&D))
{
source=0;
sink=2*N+F+D+1;
init();
for(int i=1;i<=F;i++)
{
scanf("%d",&num);
addedge(source,i,num);//源点指向所有食物
}

for(int i=F+2*N+1;i<=F+2*N+D;i++)
{
scanf("%d",&num);
addedge(i,sink,num);//所有饮料指向汇点
}
for(int i=F+1;i<=F+N;i++)//吃饭的人指向喝饮料的人
addedge(i,i+N,1);
for(int i=1;i<=N;i++)
{
cin>>req;
for(unsigned int j=0;j<req.size();j++)
{
if(req[j]=='Y')
addedge(j+1,i+F,1);//饭指向人
}
}
for(int i=1;i<=N;i++)
{
cin>>req;
for(unsigned int j=0;j<req.size();j++)
{
if(req[j]=='Y')
addedge(F+N+i,j+2*N+F+1,1);//人指向饮料
//maze[N+i][j+2*N+F+1]=1;
}
}
ans=sap(source,sink,sink+1);
printf("%d\n",ans);

}
return 0;
}

 

查看原文:http://colorfulshark.cn/wordpress/food-1014.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: