您的位置:首页 > 其它

hdu 4322 Candy 费用流

2014-04-22 14:28 337 查看
题解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
,s,t,cnt,n,m,ans;
int d
,pre
;
bool vis
;
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\n",cas);
else printf("Case #%d: NO\n",cas);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: