题意:

n个糖果,m个孩子,给一个矩阵like[i][j]表示第i个孩子喜欢第j个糖果。 如果孩子拿到他喜欢的糖果,那么他将会增加k个快乐度,拿到不喜欢的,增加1。 如果孩子i的欢乐值大于B[i],那么他就是开心的。

问,能否有一种分配方案,让所有孩子都开心,有输出yes,没有no。

思路:(讲的不好请见谅,大牛勿喷)

起初是看了一个大牛的一篇关于网络流建模的总结,里面有个跟这个题同名的题,只是它里面k是固定的就是2.里面的做法是用单纯的最大流做的,没有考虑到费用。建图是这样的,每颗糖作为一个点连边(s,i,1),每个小孩j座位一个点连边(j,t,b[i]/2),若小孩j喜欢糖果i则连边(i,j,1),然后最大流一下,得ans,,ans+n>=求和(b[i]).他的考虑是反正每颗糖最后都是要分给孩子的,那么它一定会为总权值贡献1,所以这个1就不考虑了,最后加上n,只考虑如果孩子喜欢这个糖而带来的额外的贡献,上述题里面这样做是没问题的。其实这两道题的思路很像,hdu4322应该是改变自上述题的,将k变成了变化的,而不是2了。

一开始我拿到这个题的时候,就直接套了上述题的思路,想将小孩j作为一个点练边(j,t,b[i]/k),表示该孩子能用b[i]/k块糖果填补一下快乐度,走一边最大流,然后用剩下的n-ans块糖来填补这些孩子不够的快乐度。后来一想这样做是不对的,比如k=3,b[i]%k==2,如果套上述建图方法,也就是说我需要用两块糖来填补这个孩子的快乐度,并且这两块糖里面可能会有他喜欢的糖果,因为走最大流的时候只让它满足了b[i]/k个流量。但这时你给这个孩子一个他喜欢的糖果,快乐度会超出1,但是糖果使用上是更少了,这是更合理的。所以只用最大流是错的。这时候就想到了需要用到费用流。

其中的总费用代表了给这些孩子喜欢的糖果所能得到的总贡献,每给一个孩子一块它喜欢的糖果,其费用是k,而且每个孩子的快乐度到达b[i]即可,就算超过了也按b[i]算,因为超过的部分没有意义。然后呢,详细考虑一下,如果一个孩子b[i]%k==0 那么建边(j,t,b[i]\k,k),容量是b[i]\k,费用是k,那么如果b[i]%k!=0呢?

如果==1,也就是说剩余的快乐度就算你给他喜欢的糖果效果也跟普通糖果一样,这时候就不需要建边了。如果>1,这时候就需要再建第二条边(j,t,1,b[i]%k),容量是1,费用是b[i]%k,它的意义就是用一个喜欢的糖果把b[i]%k的部分填补掉。但这时候再考虑一个问题,就是如果你套最小费用最大流的板子,它肯定会先走第二条边,但这样是不对的。这样的话就有可能导致费用是k的边的容量有剩余时,而第二条边已经被流了,道理自己想吧。所以我们需要做的就是先让它流费用大的,所以这是个最大费用最大流。只需要把费用取相反数,流完再取反就好了。

最后判断n-ans>=all(b[i])-cost是否成立就好了,也就是剩余的没人喜欢(或者被某些孩子喜欢但这个孩子快乐度够了而不能要)的糖果是不是能满足剩余的快乐度。

代码:最小费用流的板子屯一发

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=1<<29;
const int maxn=1000;struct node
{int v,next,cap,w;
};
node edge[maxn<<1];
int head[maxn];
int cnt;
int dis[maxn],pe[maxn],pv[maxn];
int m,n,k;
int cost,flow;
int S,T,all;
bool mark[maxn];void init()
{memset(head,-1,sizeof(head));cnt=0;all=0;
}void add(int a,int b,int c,int d)
{edge[cnt].v=b;edge[cnt].cap=c;edge[cnt].w=d;edge[cnt].next=head[a];head[a]=cnt++;edge[cnt].v=a;edge[cnt].cap=0;edge[cnt].w=-d;edge[cnt].next=head[b];head[b]=cnt++;
}int mindinic()
{int Min;cost=0,flow=0;while(1){for(int i=0;i<=T;i++) dis[i]=inf;memset(mark,false,sizeof(mark));queue<int> q;dis[0] = 0;q.push(0);mark[0]=true;int cur;while(!q.empty()){cur = q.front();q.pop();mark[cur]=false;for(int i = head[cur]; i != -1; i = edge[i].next){node x=edge[i];if(x.cap&& dis[x.v]>x.w+dis[cur] ){dis[x.v] = dis[cur] + x.w;pe[x.v]=i;pv[x.v]=cur;if(!mark[x.v]){mark[x.v]=true;q.push(x.v);}}}}if(dis[T]==inf) return cost;Min=inf;for(int j=T; j!=S; j=pv[j])Min=min(Min,edge[pe[j]].cap);flow+=Min;cost+=dis[T]*Min;for(int j=T; j!=S; j=pv[j])edge[pe[j]].cap-=Min,edge[pe[j]^1].cap+=Min;}
}int main()
{int cas=1;int t,x;scanf("%d",&t);while(t--){scanf("%d%d%d",&n,&m,&k);init();S=0,T=n+m+1;for(int i=1; i<=n; i++){add(S,i,1,0);}for(int i=1; i<=m; i++){scanf("%d",&x);all+=x;add(n+i,T,x/k,-k);if(x%k>1){add(n+i,T,1,-x%k);}}for(int i=1; i<=m; i++){for(int j=1; j<=n; j++){scanf("%d",&x);if(x){add(j,n+i,1,0);}}}int tmp=-mindinic();//用上的喜欢的糖果能够填充的快乐度if(n-flow>=all-tmp)//剩余的没人喜欢的糖果是否能填充剩余的快乐度printf("Case #%d: YES\n",cas++);elseprintf("Case #%d: NO\n",cas++);}return 0;
}

hdu4322 candy 费用流相关推荐

  1. BZOJ3130: [Sdoi2013]费用流[最大流 实数二分]

    3130: [Sdoi2013]费用流 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special Judge Submit: 960  Solved:  ...

  2. [BZOJ 1221][HNOI2001]软件开发(费用流)

    Description 某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员 ...

  3. 费用流 -- 四川省赛F-Direction Setting [拆边成点+费用流]

    题目链接 题目大意: 就是给你一个nnn个点mmm条边的无向图,每个点有个值是aia_iai​现在你把每条边都赋予一个方向之后这个图就是有向图了,那么设第iii个点的入度是did_idi​,现在设 D ...

  4. UVA1411 Ants(带权二分图的最大完美匹配、zkw费用流)

    题解 给定一些黑点白点,要求一个黑点链接一个白点并且线段不相交(转成二分图最大权匹配使用费用流解决)<训练指南>P351 输出方案:满流即为答案(满流是指这条路的流量跑满了,也就是说edg ...

  5. 餐巾计划问题 线性规划与网络流24题之10 费用流

    相关知识:最小费用(最大)流 问题描述: 一个餐厅在相继的N 天里, 每天需用的餐巾数不尽相同. 假设第i天需要ri块餐巾(i=1, 2,-,N).餐厅可以购买新的餐巾,每块餐巾的费用为p分:或者把旧 ...

  6. BZOJ1150[CTSC2007]数据备份Backup——模拟费用流+堆+链表

    题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游 ...

  7. bzoj3171: [Tjoi2013]循环格(费用流)

    传送门 其实这题的建图并不难(虽然我并没有想出来) 首先,每一个点的入度和出度必须为$1$ 那么我们考虑拆点 每个点的出度点向它能到达的点的入度点连边,容量$1$,如果方向为原来的方向则费用$0$否则 ...

  8. 洛谷 - P2045 - 方格取数加强版 - 费用流

    原来这种题的解法是费用流. 从一个方格的左上走到右下,最多走k次,每个数最多拿走一次. 每次走动的流量设为1,起始点拆点成限制流量k. 每个点拆成两条路,一条路限制流量1,费用为价值相反数.另一条路无 ...

  9. 【BZOJ2245】[SDOI2011]工作安排 拆边费用流

    [BZOJ2245][SDOI2011]工作安排 Description 你的公司接到了一批订单.订单要求你的公司提供n类产品,产品被编号为1~n,其中第i类产品共需要Ci件.公司共有m名员工,员工被 ...

最新文章

  1. 离线轻量级大数据平台Spark之单机部署及Java开发
  2. 平台型OA=高性价比OA?
  3. AngularJS 日期格式化
  4. consul宕机配置丢失_简单的配置死机
  5. 一行Python代码就可以下载任意网站视频,零基础小白也能轻松学会
  6. Worktile 移动团队如何使用 C++ 完成 Worktile Pro 跨平台应用开发2
  7. python能做什么程序-python能做哪些生活有趣的事情
  8. 这是我的第一篇博文,请大家多多关照!~
  9. 08.Prevent exceptions from leaving destructors
  10. andriod 获取attrs_Android:具有attrs.xml中对象引用的Custom View,...
  11. 第 14 章 SMS
  12. 使用python print打印函数返回值多一个None的问题探究
  13. 你的伙伴对你最大会话_当你给朋友打电话的时候,最搞笑的一句回话是什么?...
  14. 微信公众号发布svg排版文章
  15. 3D动作手游的辅助瞄准算法(三)
  16. Tokio教程之select
  17. TCP 的那些事 | SACK
  18. java用户名重复验证代码_java如何让注册的用户名不重复,在当前页面就可以判断,并抛出提示?...
  19. 数据中台已成下一风口,它会颠覆数据工程师的工作吗?
  20. Python 基礎 - 文件操作_v2

热门文章

  1. Typhon爬取图片
  2. Mac如何给压缩文件加密
  3. 什么叫域名解析SSL证书?
  4. “XXX停止运行”问题解决
  5. C++ 读取TXT文件中的数据 每一行空格符相隔的数据单独取出
  6. please insert the disc labeled ‘Ubuntu 18.04.5 LTS _Bionic Beaver_ - Release amd64 (20200806.1)‘ in
  7. “红山开源”创新论坛 | ChinaOSC
  8. 史济怀20180915_1 有限覆盖定理
  9. PLSQL的JOB启动与停止(可视化操作)
  10. GitHub搜索技巧整理