这道题就是“修车”的数据加强版……但是数据范围扩大了好多,应对方法是“动态开点”。

首先先把“所有厨师做的倒数第一道菜”和所有菜连边,然后跑一下spfa,找出哪一个厨师在增广路上,把“这个厨师做的倒数第二道菜”和所有菜连边,然后继续spfa,如此循环往复直到spfa找不出最短路。

  1. #include <queue>
  2. #include <cstdio>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <algorithm>
  6. #include <iostream>
  7. #define space putchar(' ')
  8. #define enter putchar('\n')
  9. typedef long long ll;
  10. using namespace std;
  11. template <class T>
  12. void read(T &x){
  13. char c;
  14. bool op = 0;
  15. while(c = getchar(), c < '0' || c > '9')
  16. if(c == '-') op = 1;
  17. x = c - '0';
  18. while(c = getchar(), c >= '0' && c <= '9')
  19. x = x * 10 + c - '0';
  20. if(op) x = -x;
  21. }
  22. template <class T>
  23. void write(T x){
  24. if(x < 0) putchar('-'), x = -x;
  25. if(x >= 10) write(x / 10);
  26. putchar('0' + x % 10);
  27. }
  28. const int N = 100005, M = 10000005, INF = 0x3f3f3f3f;
  29. int n, m, src, des, tot, ans, sum;
  30. int cook[105][805], dish[805], id[N], rnk[N], w[45][105], p[45];
  31. int ecnt = 1, adj[N], dis[N], pre[N], nxt[M], go[M], cap[M], cost[M];
  32. void _add(int u, int v, int w, int c){
  33. go[++ecnt] = v;
  34. nxt[ecnt] = adj[u];
  35. adj[u] = ecnt;
  36. cap[ecnt] = w;
  37. cost[ecnt] = c;
  38. }
  39. void add(int u, int v, int w, int c){
  40. _add(u, v, w, c);
  41. _add(v, u, 0, -c);
  42. }
  43. bool spfa(){
  44. queue <int> que;
  45. static bool inq[N] = {0};
  46. for(int i = 1; i <= tot; i++)
  47. dis[i] = INF, pre[i] = 0;
  48. dis[src] = 0, que.push(src), inq[src] = 1;
  49. while(!que.empty()){
  50. int u = que.front();
  51. que.pop(), inq[u] = 0;
  52. for(int e = adj[u], v; e; e = nxt[e]){
  53. if(cap[e] && dis[u] + cost[e] < dis[v = go[e]]){
  54. dis[v] = dis[u] + cost[e], pre[v] = e;
  55. if(!inq[v]) que.push(v), inq[v] = 1;
  56. }
  57. }
  58. }
  59. return dis[des] < INF;
  60. }
  61. int main(){
  62. read(n), read(m);
  63. src = ++tot, des = ++tot;
  64. for(int i = 1; i <= n; i++)
  65. read(p[i]), sum += p[i];
  66. for(int i = 1; i <= n; i++)
  67. for(int j = 1; j <= m; j++)
  68. read(w[i][j]);
  69. for(int i = 1; i <= n; i++){
  70. dish[i] = ++tot, id[tot] = i;
  71. add(src, dish[i], p[i], 0);
  72. }
  73. for(int i = 1; i <= m; i++){
  74. cook[i][1] = ++tot, id[tot] = i, rnk[tot] = 1;
  75. add(cook[i][1], des, 1, 0);
  76. for(int j = 1; j <= n; j++)
  77. add(dish[j], cook[i][1], 1, w[j][i]);
  78. }
  79. while(spfa()){
  80. int tmp = go[pre[des] ^ 1], _cook = id[tmp], _rank = rnk[tmp], flow = INF;
  81. for(int e = pre[des]; e; e = pre[go[e ^ 1]])
  82. flow = min(flow, cap[e]);
  83. for(int e = pre[des]; e; e = pre[go[e ^ 1]])
  84. cap[e] -= flow, cap[e ^ 1] += flow;
  85. ans += flow * dis[des];
  86. cook[_cook][_rank + 1] = ++tot, id[tot] = _cook, rnk[tot] = _rank + 1;
  87. add(tot, des, 1, 0);
  88. for(int i = 1; i <= n; i++)
  89. add(dish[i], tot, 1, w[i][_cook] * (_rank + 1));
  90. }
  91. write(ans), enter;
  92. return 0;
  93. }

BZOJ 2879 [Noi2012]美食节 | 费用流 动态开点的更多相关文章

  1. BZOJ 2879: [Noi2012]美食节( 费用流 + 动态加边 )

    倒着做菜..然后考虑为当前的人做菜对后面的人的影响就可以了..要动态加边 --------------------------------------------------------------- ...

  2. BZOJ.2879.[NOI2012]美食节(费用流SPFA)

    题目链接 /* 同"修车":对于每个厨师拆成p个点表示p个时间点,每个人向m个厨师每个时间点连边 这样边数O(nmp)+网络流 ≈O(nm*p^2)(假设SPFA线性) = GG ...

  3. 【bzoj2879】[Noi2012]美食节 费用流+动态加边

    原文地址:http://www.cnblogs.com/GXZlegend 题目描述 CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他 ...

  4. [BZOJ2879] [Noi2012] 美食节 (费用流 & 动态加边)

    Description CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽 ...

  5. BZOJ 2879: [Noi2012]美食节 最小费用流 动态添边

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 324  Solved: 179[Submit][Status] ...

  6. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  7. [NOI2012]美食节——费用流(带权二分图匹配)+动态加边

    题目描述 小M发现,美食节共有n种不同的菜品.每次点餐,每个同学可以选择其中的一个菜品.总共有m个厨师来制作这些菜品.当所有的同学点餐结束后,菜品的制作任务就会分配给每个厨师.然后每个厨师就会同时开始 ...

  8. [NOI2012][bzoj2879] 美食节 [费用流+动态加边]

    题面 传送门 思路 先看看这道题 修车 仔细理解一下,这两道题是不是一样的? 这道题的不同之处 但是有一个区别:本题中每一种车有多个需求,但是这个好办,连边的时候容量涨成$p\lbrack i\rbr ...

  9. [NOI2012]美食节(费用流)

    题目描述 CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽管所有的菜品都 ...

随机推荐

  1. 20155325 Exp3 免杀原理与实践

    基础问题回答 杀软是如何检测出恶意代码的? 1.1 基于特征码的检测 1.1.1 特征库举例-Snort 1.2 启发式恶意软件检测 1.3 基于行为的恶意软件检测 免杀是做什么? 一般是对恶意软件做 ...

  2. Lambda学习---方法引用和其他基本应用

    package com.zx; import java.util.*; import java.util.function.*; import java.util.stream.Collectors; ...

  3. NodeJS旅程 : Less

    我一直强调我是个很懒的人,虽然我认为自己是个代码控但不代表我喜欢写大量代码.有做Web前端开发的人一定都接触CSS,由其在当下CSS3更是做出Cool站的必修课.我曾和不少的前端开发讨论过CSS3,我 ...

  4. 浅谈android Service和BroadCastReceiver

    1.题记 Android中的服务和windows中的服务是类似的东西,服务一般没有用户操作界面,它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序. 广播接收者(BroadcastRece ...

  5. MongoDB的账户与权限管理及在Python与Java中的登录

    本文主要介绍了MongoDB的账户新建,权限管理(简单的),以及在Python,Java和默认客户端中的登陆. 默认的MongoDB是没有账户权限管理的,也就是说,不需要密码即可登陆,即可拥有读写的权 ...

  6. npm install的几种命令形式区别

    转自未来与传说.jigetage 我们在使用 npm install 安装模块的时候 ,一般会使用下面这几种命令形式: npm install moduleName # 安装模块到项目目录下 npm ...

  7. Python提示信息表示内容

      =此页面列出了PyLint 1.1.0支持的所有消息,按消息文本排序.还有一个按消息代码排序的所有代码列表. E0001,F0001,W0511(消息不同) E0103:循环中%r不正确W1501 ...

  8. Eclipse,代码中有错误,项目中却不显示红叉

    ***修改eclipse 代码提示级别1.单个项目修改项目上右键-->properties-->java compiler-->building-->enable projec ...

  9. Spark 实践——用决策树算法预测森林植被

    本文基于<Spark 高级数据分析>第4章 用决策树算法预测森林植被集. 完整代码见 https://github.com/libaoquan95/aasPractice/tree/mas ...

  10. 从零开始学Kotlin-基础语法(1)

    从零开始学Kotlin基础篇系列文章 注释 //单行注释 /* 多行注释 */ /** * 多行注释 */ 定义变量/常量 变量定义:var 关键字 var <标识符> : <类型& ...