Food (拆点 Dinic模板)

 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


题意:与牛Dining类似,N个人,F中食物,D中饮料;第二行有F个数,表示每种食物的个数,第三行有D个数,表示每种饮料的个数;接下来4~N+4行,每行有F个字符,表示对每种食物的爱好,N+5~最后,表示对每种饮料的爱好;

对人拆点,容量为1,汇点指向食物,容量为食物的个数,饮料指向汇点,容量为饮料的个数;Dinic模板



#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<string>
using namespace std;
const int MAXN=1000+10;
const int inf=0x3f3f3f3f3f;
int n,F,D,N;
int edn;//边数
int dis[MAXN],head[MAXN];
struct node
{
    int v,w;
    int next;
}Edge[MAXN*MAXN];
void AddEdge(int u,int v,int w)//邻接表存图
{
    Edge[edn].v=v,Edge[edn].w=w;
    Edge[edn].next=head[u],head[u]=edn++;

    Edge[edn].v=u,Edge[edn].w=0;
    Edge[edn].next=head[v],head[v]=edn++;
}
int bfs()
{
    queue<int>s;
    memset(dis,-1,sizeof(dis));
    dis[0]=0;
    s.push(0);
    while(!s.empty())
    {
        int now=s.front();
        s.pop();
        for(int i=head[now];i!=-1;i=Edge[i].next)
        {
            int u=Edge[i].v;
            if(dis[u]==-1&&Edge[i].w>0)//只考虑网络中有残量的弧
            {
                dis[u]=dis[now]+1;
                s.push(u);
            }
        }
    }
    return dis[N+1]!=-1;
}
int dfs(int a,int b)
{
    if(a==N+1) return b;
    int flow;
    for(int i=head[a];i!=-1;i=Edge[i].next)
    {
        int u=Edge[i].v;
        if(dis[a]+1==dis[u]&&Edge[i].w>0&&(flow=dfs(u,min(b,Edge[i].w)))>0)
        {
            Edge[i].w-=flow;
            Edge[i^1].w+=flow;
            return flow;
        }
    }
    dis[a]=-1;
    return 0;
}
int Dinic()
{
    int flow=0,temp;
    while(bfs())
    {
        while(temp=dfs(0,inf))
        flow+=temp;
    }
    return flow;
}
int main()
{
   while(~scanf("%d%d%d",&n,&F,&D))
   {
       N=2*n+F+D;
       memset(head,-1,sizeof(head));
       edn=0;
       int a;
       for(int i=1;i<=F;i++)
       {
           scanf("%d",&a);
           AddEdge(0,2*n+i,a);
       }
       for(int i=1;i<=D;i++)
       {
           scanf("%d",&a);
           AddEdge(2*n+F+i,N+1,a);
       }
       char s[MAXN];
       for(int i=1;i<=n;i++)
       {
           scanf("%s",s);
           for(int j=1;j<=F;j++)
           {
               if(s[j-1]=='Y')
               {
                   AddEdge(2*n+j,i,1);
               }
           }
           AddEdge(i,n+i,1);
       }
       for(int i=1;i<=n;i++)
       {
           scanf("%s",s);
           for(int j=1;j<=D;j++)
           {
               if(s[j-1]=='Y')
               {
                   AddEdge(n+i,2*n+F+j,1);
               }
           }
       }
       printf("%d\n",Dinic());
   }
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值