hdu 4292 網路最大流

life4711發表於2015-04-06

http://acm.hdu.edu.cn/showproblem.php?pid=4292

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
/**
hdu 4292 網路最大流
題目大意:有F種食物,D種飲料,各有一定數量n個人,現在要求每個人的要求是1份食物1個飲料,問最多能滿足多少人的要求
解題思路:一看就是網路流的題。
         建邊思想:把n個人對應拆成個連個點i和i‘,之間連邊權值1;
                   每種食物和喜歡其的i之間權值為1的邊
                   每個人和他喜歡的飲料之間連權值為1的邊
                   起點和每種食物之間連權值為該種食物數量的邊;
                   每種飲料喝終點之間連權值為該種飲料數量的邊。
         跑一遍最大流即可。
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int oo=1e9;
const int mm=8811111;
const int mn=1212;
int node,src,dest,edge;
int ver[mm],flow[mm],_next[mm];
int head[mn],work[mn],dis[mn],q[mn];

void prepare(int _node,int _src,int _dest)
{
    node=_node,src=_src,dest=_dest;
    for(int i=0; i<node; ++i)head[i]=-1;
    edge=0;
}

void addedge(int u,int v,int c)
{
    ver[edge]=v,flow[edge]=c,_next[edge]=head[u],head[u]=edge++;
    ver[edge]=u,flow[edge]=0,_next[edge]=head[v],head[v]=edge++;
}

bool Dinic_bfs()
{
    int i,u,v,l,r=0;
    for(i=0; i<node; ++i)dis[i]=-1;
    dis[q[r++]=src]=0;
    for(l=0; l<r; ++l)
        for(i=head[u=q[l]]; i>=0; i=_next[i])
            if(flow[i]&&dis[v=ver[i]]<0)
            {
                dis[q[r++]=v]=dis[u]+1;
                if(v==dest)return 1;
            }
    return 0;
}

int Dinic_dfs(int u,int exp)
{
    if(u==dest)return exp;
    for(int &i=work[u],v,tmp; i>=0; i=_next[i])
        if(flow[i]&&dis[v=ver[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)
        {
            flow[i]-=tmp;
            flow[i^1]+=tmp;
            return tmp;
        }
    return 0;
}
int Dinic_flow()
{
    int i,ret=0,delta;
    while(Dinic_bfs())
    {
        for(i=0; i<node; ++i)work[i]=head[i];
        while(delta=Dinic_dfs(src,oo))ret+=delta;
    }
    return ret;
}
int n,D,F,f[205],d[205];
char a[1005];

int main()
{
    while(~scanf("%d%d%d",&n,&F,&D))
    {
        prepare(n*2+F+D+2,0,F+D+2*n+1);
        for(int i=1;i<=F;i++)
        {
            int x;
            scanf("%d",&x);
            addedge(src,i,x);
        }
        for(int i=1;i<=D;i++)
        {
            int x;
            scanf("%d",&x);
            addedge(i+F+n*2,dest,x);
        }
        for(int i=1;i<=n;i++)
        {
            addedge(i+F,i+n+F,1);
            scanf("%s",a+1);
            for(int j=1;j<=F;j++)
            {
                if(a[j]=='Y')
                    addedge(j,i+F,1);
            }
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%s",a+1);
            for(int j=1;j<=D;j++)
            {
                if(a[j]=='Y')
                    addedge(i+F+n,F+n*2+j,1);
            }
        }
        printf("%d\n",Dinic_flow());
    }
    return 0;
}


相關文章