zoukankan      html  css  js  c++  java
  • hdu 4322 Candy 费用流

    题解copy别人的。。

    Candy
    【题目大意】
    有N颗糖果和M个小孩,老师现在要把这N颗糖分给这M个小孩。每个小孩i对每颗糖j都有一个偏爱度Aij,如果他喜欢这颗糖,Aij = k,否则Aij = 1。小孩i觉得高兴当且仅当ΣCij×Aij >= Bi,j=1,2,…,N,若他分得了糖j,Cij = 1,否则Cij = 0。问能否合理分配这N颗糖,使得每个小孩都觉得高兴。
    【建模方法】
    (最大费用最大流)
     本题有一个突破点就是:他喜欢这颗糖,Aij = k,否则Aij = 1,关键在于如果他不喜欢这个糖分给他一样可以获得1点的欢乐值。也就是说如果之前分配了的糖给了小孩一定的欢乐值,不够bi,可以直接用随意的糖去填满。
    首先我们要求欢喜值>=bi,是否可以认为当我获得欢喜值为bi后,多余欢喜值对这个结果的满足是没有贡献的。也就是说,你可以用一个容量来控制分配糖对小孩欢喜值的控制,让获得欢喜值最多为bi。如果不够,最后用一些1的糖来填满。
    而这个容量就是bi/c,获取贡献为k,bi%c(>1)的也是可以用一个能让这个小孩欢喜的糖来贡献,但是其费用只为bi%c。
    对于小孩来说,最大费用最大流后,糖分配的贡献值为最大费用,剩余糖就是(n-最大流),然后用这些糖去填不满的,只要满足总和大于Σbj。就可以分配了。


    具体建模方案1:
    (s,i,1,0);
    (i,j,1,0);
    (j,t,bj/k,k);
    If(bj%k>1)
    (j,t,1,bj%k)
    Ans = 费用 + N – 最大流 >= Σbj  则满足要求
    具体建模方案2:
    (s,I,1,0)
    (I,j,1,0)
    (j,t,bj/k,k-1);
    If(bj%k>1)
    (j,t,1,bj%k-1);
    Ans = 费用+N  >= Σbj  则满足要求

    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    using namespace std;
    const int N=400;
    const int MAXE=20000000;
    const int inf=1<<30;
    int head[N],s,t,cnt,n,m,ans;
    int d[N],pre[N];
    bool vis[N];
    int q[MAXE];
    struct Edge
    {
        int u,v,c,w,next;
    }edge[MAXE];
    
    void addedge(int u,int v,int w,int c)
    {
        edge[cnt].u=u;
        edge[cnt].v=v;
        edge[cnt].w=w;
        edge[cnt].c=c;
        edge[cnt].next=head[u];
        head[u]=cnt++;
        edge[cnt].v=u;
        edge[cnt].u=v;
        edge[cnt].w=-w;
        edge[cnt].c=0;
        edge[cnt].next=head[v];
        head[v]=cnt++;
    }
    
    int SPFA()
    {
        int l,r;
        memset(pre,-1,sizeof(pre));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<=t;i++) d[i]=inf;
        d[s]=0;
        l=0;r=0;
        q[r++]=s;
        vis[s]=1;
        while(l<r)
        {
            int u=q[l++];
            vis[u]=0;
            for(int j=head[u];j!=-1;j=edge[j].next)
            {
                int v=edge[j].v;
                if(edge[j].c>0&&d[u]+edge[j].w<d[v])
                {
                    d[v]=d[u]+edge[j].w;
                    pre[v]=j;
                    if(!vis[v])
                    {
                        vis[v]=1;
                        q[r++]=v;
                    }
                }
            }
        }
        if(d[t]==inf)
            return 0;
        return 1;
    }
    
    int MCMF()
    {
        int flow=0;
        while(SPFA())
        {
            int u=t;
            int mini=inf;
            while(u!=s)
            {
                if(edge[pre[u]].c<mini)
                    mini=edge[pre[u]].c;
                    u=edge[pre[u]].u;
            }
            flow+=mini;
            u=t;
            ans+=d[t]*mini;
            while(u!=s)
            {
                edge[pre[u]].c-=mini;
                edge[pre[u]^1].c+=mini;
                u=edge[pre[u]].u;
            }
        }
        return flow;
    }
    
    int main()
    {
        int T;
        int i,j;
        int like[20][20];
        int B[20];
        int k;
        scanf("%d",&T);
        int cas=0;
        while(T--)
        {
            ans=0;
            int sum=0;
            cas++;
            scanf("%d%d%d",&n,&m,&k);
    		int i;
            s=0;t=n+m+1;cnt=0;
            for(i=0;i<=t;i++)
                head[i]=-1;
            for(i=1;i<=m;i++)
            {
                scanf("%d",&B[i]);
                sum+=B[i];
            }
            for(i=1;i<=m;i++)
                for(j=1;j<=n;j++)
                {
                    scanf("%d",&like[i][j]);
                    if(like[i][j]==1)
                        addedge(j,n+i,0,1);
                }
            for(i=1;i<=n;i++) addedge(s,i,0,1);
            for(i=1;i<=m;i++)
            {
                if(B[i]%k>1)
                {
                    addedge(i+n,t,-k,B[i]/k);
                    addedge(i+n,t,-B[i]%k,1);
                }
                else addedge(i+n,t,-k,B[i]/k);
            }
            int maxflow=MCMF();
            //printf("%d ",ans);
            if(-ans+n-maxflow>=sum)
                printf("Case #%d: YES
    ",cas);
            else printf("Case #%d: NO
    ",cas);
        }
        return 0;
    }
    


     

  • 相关阅读:
    基本控件文档-UIView属性---iOS-Apple苹果官方文档翻译
    基本控件文档-UITextField属性---iOS-Apple苹果官方文档翻译
    vue后台管理权限篇
    JavaScript call、apply、bind的用法
    Array map()方法
    markdown常用语法总结
    webpack配置说明
    Object.prototype.toString.call(value)
    前后端数据交互和前端数据展示
    vue常用的传值方式
  • 原文地址:https://www.cnblogs.com/vermouth/p/3710139.html
Copyright © 2011-2022 走看看