zoukankan      html  css  js  c++  java
  • Food(拆点建图,网络流)

      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
     
    Recommend
    liuyiding   |   We have carefully selected several similar problems for you:  4288 4296 4295 4294 4293 
     
    把每个人拆成一条容量为1的边,这样保证了人之间流量最多为1。
    然后根据匹配连,饮料在左侧,连源点,食物在右侧,连汇点。
    #include <bits/stdc++.h>
    #define maxn 10005
    using namespace std;
    struct Person
    {
        string food,drink;
    }person[maxn];
    const int inf= 1e9;
    struct Edge
    {
        int u,v,c,flow;
        Edge(int a,int b,int cc,int f):u(a),v(b),c(cc),flow(f){}
    };
    struct Dinic
    {
        int s,t;
        vector<Edge> edges;
        vector<int> pre[maxn];
        bool vis[maxn];
        int dist[maxn];
        int cur[maxn];
        void init()
        {
            for(int i=0;i<maxn;i++)
            {
                pre[i].clear();
            }
            edges.clear();
        }
        void Addedge(int u,int v,int f)
        {
            edges.push_back(Edge(u,v,f,0));
            edges.push_back(Edge(v,u,0,0));
            int mm=edges.size();
            pre[u].push_back(mm-2);
            pre[v].push_back(mm-1);
        }
        bool bfs()
        {
            memset(vis,false,sizeof(vis));
            queue<int> q;
            q.push(s);
            vis[s]=1;
            dist[s]=0;
            while(!q.empty())
            {
                int now=q.front();
                q.pop();
                for(int i=0;i<pre[now].size();i++)
                {
                    Edge &e=edges[pre[now][i]];
                    if(!vis[e.v]&&e.c>e.flow)
                    {
                        dist[e.v]=dist[now]+1;
                        vis[e.v]=true;
                        q.push(e.v);
                    }
                }
            }
            return vis[t];
        }
        int dfs(int x,int cap)
        {
            if(x==t||cap==0) return cap;
            int f,flow=0;
            for(int &i=cur[x];i<pre[x].size();i++)
            {
                cur[x]=i;
                Edge &e=edges[pre[x][i]];
                if(dist[e.v]==dist[x]+1&&(f=dfs(e.v,min(cap,e.c-e.flow))))
                   {
                       e.flow+=f;
                        edges[pre[x][i]^1].flow-=f;
                flow+=f;
                cap-=f;
                if(cap==0) break;
                   }
            }
            return flow;
        }
        int Maxflow(int s,int t)
        {
            this->s=s;
            this->t=t;
            int flow=0;
            while(bfs())
            {
                memset(cur,0,sizeof(cur));
                flow+=dfs(s,inf);
            }
            return flow;
        }
    }dc;
    int main()
    {
        int n,f,d,i;
        while(cin>>n>>f>>d)
        {
            dc.init();
        int a[maxn]={0};
        int b[maxn]={0};
            for(i=1;i<=f;i++)
        {
            scanf("%d",&a[i]);
        }
        for(i=1;i<=d;i++)
        {
            scanf("%d",&b[i]);
        }
        for(i=1;i<=n;i++)
        {
            cin>>person[i].food;
        }
        for(i=1;i<=n;i++)
        {
            cin>>person[i].drink;
        }
        for(i=1;i<=n;i++)
        {
            for(int j=0;j<f;j++)
            {
                if(person[i].food[j]=='Y')
                {
                    dc.Addedge(j+1,f+i,1);
                }
            }
        }
        for(i=1;i<=n;i++)
        {
            dc.Addedge(f+i,f+n+i,1);
        }
        for(i=1;i<=n;i++)
        {
            for(int j=0;j<d;j++)
            {
                if(person[i].drink[j]=='Y')
                {
                    dc.Addedge(f+n+i,f+2*n+j+1,1);
                }
            }
        }
        for(i=1;i<=f;i++)
        {
            dc.Addedge(0,i,a[i]);
        }
        for(i=1;i<=d;i++)
        {
            dc.Addedge(f+2*n+i,f+2*n+d+1,b[i]);
        }
        printf("%d
    ",dc.Maxflow(0,f+2*n+d+1));
        }
        return 0;
    }
    

      

     
  • 相关阅读:
    WPF常用TriggerAction用法 (一)
    一个WPF只能输入数字的行为。
    自定义panel实现,并实现item更改和移除动画。
    MVVM模式下弹出窗体
    ZAM 3D 制作简单的3D字幕 流程(二)
    ZAM 3D 制作简单的3D字幕 流程(一)
    ZAM 3D 制作3D动画字幕 用于Xaml导出
    Metro Win8风格的按钮(Filp翻转)
    WPF自动隐藏的消息框(鼠标放上去将一直显示,移开动画继续),提供normal和error两种边框。
    可分组的选择框控件(MVVM下)(Toggle样式 仿造单选框RadioButton,复选框CheckBox功能)
  • 原文地址:https://www.cnblogs.com/zyf3855923/p/9458745.html
Copyright © 2011-2022 走看看