2 3 2 2 2 2 0 0 0 0 0 1 3 2 2 2 2 0 0 0 0 0 0
Case #1: YES Case #2: NOHintGive the first and second candy to the first kid. Give the third candy to the second kid. This allocate make all kids happy.
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4322
题意:有n块糖,m个小孩,每个小孩有喜欢的糖,把他喜欢的糖给他则他获得K的 高兴值,普通糖则获得1个高兴值,求能否使得所有小孩的高兴值都大于所给值
分析:这题比赛时一开始以为是DP,优化了n久还是TLE,后来想到了网络流,构建了一个类似题解的模型,可惜我还是嫩了点。。。模型是最大流,然后剩下的特殊处理,导致错误。。。。
正解就是最大费用流,首先给每个小孩限制糖果数,用的就是最大流,也就是我一开始想到的,其次在最大流的基础上加上费用,并把每个小孩的剩余值另立一条边,然后求最大费用最大流,在这里我想喷一下数据,居然少了一组,居然还有人过了。。。我悲剧的读入矩阵时,用单个变量就悲剧了,如果用数组的话,就会保留前一组数据,答案就对了。。。悲剧啊~~~
不过这题算个好题吧
代码:
#include<cstdio> #include<iostream> #include<cstring> using namespace std; const int oo=1e9; const int mm=8888; const int mn=44; int node,src,dest,edge,need,sum; int ver[mm],cost[mm],flow[mm],next[mm]; int head[mn],dis[mn],q[mn],p[mn],b[22],a[22][22]; bool vis[mn]; void prepare(int _node,int _src,int _dest) { node=_node,src=_src,dest=_dest; for(int i=0;i<node;++i)head[i]=-1; edge=0; } void addedge(int u,int v,int f,int c) { ver[edge]=v,flow[edge]=f,cost[edge]=c,next[edge]=head[u],head[u]=edge++; ver[edge]=u,flow[edge]=0,cost[edge]=-c,next[edge]=head[v],head[v]=edge++; } bool spfa() { int i,u,v,l,r=0,tmp; for(i=0;i<node;++i)dis[i]=oo; dis[q[r++]=src]=0; p[src]=p[dest]=-1; for(l=0;l!=r;++l>=mn?l=0:l) for(i=head[u=q[l]],vis[u]=0;i>=0;i=next[i]) if(flow[i]&&dis[v=ver[i]]>(tmp=dis[u]+cost[i])) { dis[v]=tmp; p[v]=i^1; if(vis[v])continue; vis[q[r++]=v]=1; if(r>=mn)r=0; } return p[dest]>-1; } int SpfaFlow() { int i,ret=0,delta; while(spfa()) { for(i=p[dest],delta=oo;i>=0;i=p[ver[i]]) if(flow[i^1]<delta)delta=flow[i^1]; for(i=p[dest];i>=0;i=p[ver[i]]) flow[i]+=delta,flow[i^1]-=delta; ret-=delta*dis[dest]; sum+=delta; } return ret; } int main() { int i,j,n,m,k,t,cs=0; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&k); prepare(n+m+2,0,n+m+1); for(i=1;i<=n;++i) addedge(src,i,1,0); sum=need=0; for(i=1;i<=m;++i) { scanf("%d",&b[i]); if(b[i]>=k)addedge(n+i,dest,b[i]/k,-k); if(b[i]%k>1)addedge(n+i,dest,1,-(b[i]%k)); need+=b[i]; } for(i=1;i<=m;++i) for(j=1;j<=n;++j) { scanf("%d",&a[i][j]); if(a[i][j])addedge(j,n+i,1,0); } need-=SpfaFlow(); printf("Case #%d: ",++cs); if(n-sum>=need)puts("YES"); else puts("NO"); } return 0; }