H - Food HDU - 4292 -网络流-拆点

  • H - Food

     HDU - 4292 
  • 题意:给定N个人、F种食物、M种饮料以及每种食物数量、每种饮料数量。 
  • 通过一个N*F的矩阵给出某个人是否接受某种食物。 
  • 再通过一个N*M矩阵给出某个人是否接受某种饮料。 
  • 顾客的要求是同时有饮料和食物(即其接受的饮料至少提供一瓶,接受的食物至少提供一份)。 
  • 求最多能满足多少位顾客。
  • 思路:顾客同时需要满足饮料和食物两种需求,可以引一条从食物到顾客的有向弧、一条顾客到饮料的有向弧。那么每一条可行流都对应一个被满足的顾客,但不是一一对应。要满足一一对应关系,即顾客结点的结点容量为1,需要将顾客进行拆点。顾客u拆成u1和u2,u1、u2之间连一条容量为u结点容量的有向弧。原指向u的边改成指向u1,原从u指出的边改成从u2指出。 
  • 如此,将饮料看作源点、食物看作汇点,这就是一个多源多汇模型。每条流量对应一个被满足的顾客。 
  • 解决多源多汇模型,设立一个超级源点S,引入从S到源点的有向弧,容量为1.设立一个超级汇点T,引入汇点到超级汇点的有向弧,容量为1. 超级源点到超级汇点的最大流即为答案。
  • #include<bits/stdc++.h>
    using namespace std;
    #define maxn 2200
    int d,n,f,a[maxn],b[maxn],deep[maxn];
    int head[maxn],cnt,s,s1,sum;
    char c;
    struct node
    {
        int v,w,to;
    } edge[maxn*200];
    void init()
    {
        cnt=-1;
        memset(head,-1,sizeof(head));
    }
    void add(int u,int v,int w)
    {
        edge[++cnt].v=v;
        edge[cnt].to=head[u];
        head[u]=cnt;
        edge[cnt].w=w;
        edge[++cnt].v=u;
        edge[cnt].to=head[v];
        head[v]=cnt;
        edge[cnt].w=0;
    }
    bool dinic_bfs()
    {
        memset(deep,0,sizeof(deep));
        queue<int>que;
        while(!que.empty())que.pop();
        que.push(0);
        deep[0]=1;
        while(!que.empty())
        {
            int u=que.front();
            que.pop();
            for(int i=head[u]; i!=-1; i=edge[i].to)
            {
                int v=edge[i].v;
                if(deep[v]==0&&edge[i].w>0)
                {
                    deep[v]=deep[u]+1;
                    que.push(v);
                }
            }
        }
        return deep[sum]!=0;
    }
    int dinic_dfs(int u,int cpflow)
    {
        if(u==sum)return cpflow;
        int addflow=0;
        for(int i=head[u]; i!=-1&&cpflow; i=edge[i].to)
        {
            int v=edge[i].v;
            if(deep[u]+1==deep[v]&&edge[i].w>0)
            {
                int temp=dinic_dfs(v,min(edge[i].w,cpflow-addflow));
                if(temp>0)
                {
                    edge[i].w-=temp;
                    edge[i^1].w+=temp;
                    addflow+=temp;
                }
            }
        }
        return addflow;
    }
    void dinic()
    {
        int maxflow=0;
        while(dinic_bfs())
        {
            maxflow+=dinic_dfs(0,sum);
        }
        printf("%d\n",maxflow);
    }
    int main()
    {
        while(scanf("%d%d%d",&n,&f,&d)!=EOF)
        {
            init();
            sum=n+f+n+d+1;
            s=n+f+n;
            s1=n+f;
            for(int i=1; i<=n; i++)
                add(f+i,s1+i,1);
            for(int i=1; i<=f; i++)
            {
                scanf("%d",&a[i]);
                add(0,i,a[i]);
            }
            for(int i=1; i<=d; i++)
            {
                scanf("%d",&b[i]);
                add(s+i,sum,b[i]);
            }
            for(int i=1; i<=n; i++)
            {
                getchar();
                for(int j=1; j<=f; j++)
                {
                    scanf("%c",&c);
                    if(c=='Y')
                        add(j,f+i,1);
                }
            }
            for(int i=1; i<=n; i++)
            {
                getchar();
                for(int j=1; j<=d; j++)
                {
                    scanf("%c",&c);
                    if(c=='Y')
                        add(s1+i,s+j,1);
                }
            }
            dinic();
        }
        return 0;
    }
    

猜你喜欢

转载自blog.csdn.net/BePosit/article/details/83957083
今日推荐