HDU 4292 Food 网络流最大流 拆点

 
 
在使用网络流之前,最重要的一件事就是构造流量图,必须保证从源点到汇点的一条路径是一个可行解才行。 对于这道题目,由于每个人既要吃饭,还要喝饮料,因此就不能把一个人当成“一”个人看待,因为如果看成一个人,那么无论怎么建图,都无法保证从源到汇的路径是可行解,这时候我们就需要将一个人拆成两个,一个负责吃饭,一个负责喝饮料,然后再让吃饭的人指向喝饮料的人,容量为1。最后在建立食物与人的边喝人与饮料的边,说起来比较抽象,见下图。 c84db2a4-9f00-37b7-ae37-075c5f843d25 (2)
Problem - 4292<script src="/js/global.js" type="text/javascript"></script><script src="/js/register.js" type="text/javascript"></script><script src="/js/MathJax/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script>

Food

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4534    Accepted Submission(s): 1533
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
Source
#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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值