题面

​ 又一次考试网络流爆零......

​ 这一题一看就是网络流, 但是要怎么构图呢? 考虑到途中的一些因素, 首先, 每一种志愿者控制的区间范围为\(S_{i}\)到\(T_{i}\), 所以, 我们要使得每种志愿者只能控制这段区间, 其他的不能够控制, 其次, 每个时间都有一个最小的值, 也就是这条边(我们将时间段看为一条边更加方便)有一个下界, 想到了什么, 上下界网络流, 每条边都要符合上界和下界的约束, 没有学过的可以戳一下.

​ 那么初始的构图也就出来了, 每个时间作为一条边, 那么由\(i\)向\(i + 1\)连一条边, 容量为\(INF - lower(i)\), 费用为0(由于人是控制一段区间的, 他在这段区间中的任意两个点流费用都为0, 可以看做这个人继续做事, 已经付钱了, 你得给我做完事才能走)(\(lower(i)\)代表时间\(i\)最少需要多少人, 其实这条边容量为\(INF\)没有问题, 假装上界为\(INF + lower(i)\)就可以了, 反正可以不停地流), 考虑到之前所说, 每个点只能约束自己的一段区间, 有点像循环流, 从\(S_{i}\)出发, 流到\(T_{i}\)就重新流, 但是这里由于\(T_{i}\)被看成了一条边, 所以我们需要在点\(T_{i} + 1\)往\(S_{i}\)连一条容量为\(INF\), 费用为\(c\)的边, 代表当前类\(i\)的志愿者控制且只能控制\(S_{i}\)到\(T_{i}\)这段时间.

​ 最终构图是这样的: 每个点\(i\)向\(i + 1\)连边, 每个\(T_{i} + 1\)向\(S_{i}\)连边, 注意在每个点\(i\)向\(i + 1\)连边时, 由于你是默认这条边流了一个下界的, 你每个点的流量不一定平衡, 记录一下每个点流入和流出的差, 对于一条下界为\(x\)的边i -> i + 1, 记\(delta[i]\)为点\(i\)流入与流出的差, 则\(delta[i] -= x\), \(delta[i + 1] += x\), 连完所有边后, 注意到每个点的\(delta\)不一定为0, 对于\(delta\)大于或者小于0的情况, 戳上面那个吧, 有详细的介绍, 最后跑一遍无源汇上下界最小费用可行流就可以了, 也就是在构出的有源汇的图中跑一遍最小费用最大流即可.

具体代码

  1. #include <iostream>
  2. #include <cstring>
  3. #include <cstdio>
  4. #include <queue>
  5. #define N 2005
  6. #define INF 1e9
  7. using namespace std;
  8. int n, m, S, T, delta[N], head[N], cnt = 1, p[N], vis[N];
  9. struct node
  10. {
  11. int from, to, next;
  12. long long flow, cost;
  13. } edge[100005];
  14. long long a[N], d[N];
  15. inline int read()
  16. {
  17. int x = 0, w = 1;
  18. char c = getchar();
  19. while(c < '0' || c > '9') { if (c == '-') w = -1; c = getchar(); }
  20. while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
  21. return x * w;
  22. }
  23. inline void add(int u, int v, long long w, long long cost)
  24. {
  25. edge[++cnt] = { u, v, head[u], w, cost }; head[u] = cnt;
  26. edge[++cnt] = { v, u, head[v], 0, -cost }; head[v] = cnt;
  27. }
  28. bool SPFA(long long &cost)
  29. {
  30. memset(d, 0x3f, sizeof(d)); memset(a, 0x3f, sizeof(a));
  31. queue<int> q; q.push(S); d[S] = 0; vis[S] = 1;
  32. while(!q.empty())
  33. {
  34. int u = q.front(); q.pop(); vis[u] = 0;
  35. for(int i = head[u]; i; i = edge[i].next)
  36. {
  37. int v = edge[i].to;
  38. if(d[v] > d[u] + edge[i].cost && edge[i].flow > 0)
  39. {
  40. d[v] = d[u] + edge[i].cost; a[v] = min(a[u], edge[i].flow);
  41. p[v] = i; if(!vis[v]) { vis[v] = 1; q.push(v); }
  42. }
  43. }
  44. }
  45. if(d[T] == d[0]) return 0;
  46. cost += (a[T] * d[T]);
  47. for(int i = T; i != S; i = edge[p[i]].from)
  48. {
  49. edge[p[i]].flow -= a[T]; edge[p[i] ^ 1].flow += a[T];
  50. }
  51. return 1;
  52. }
  53. int main()
  54. {
  55. n = read(); m = read();
  56. S = n + 2; T = S + 1;
  57. for(int i = 1; i <= n; i++) { int x = read(); add(i, i + 1, INF, 0); delta[i] -= x; delta[i + 1] += x; }
  58. for(int i = 1; i <= m; i++)
  59. {
  60. int u = read(), v = read(), c = read();
  61. add(v + 1, u, INF, c);
  62. }
  63. for(int i = 1; i <= n + 1; i++)
  64. {
  65. if(delta[i] < 0) add(i, T, -delta[i], 0);
  66. if(delta[i] > 0) add(S, i, delta[i], 0);
  67. }
  68. long long cost = 0;
  69. while(SPFA(cost));
  70. printf("%lld\n", cost);
  71. return 0;
  72. }

[luogu3980] 志愿者招募的更多相关文章

  1. BZOJ 1061: [Noi2008]志愿者招募

    1061: [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 4064  Solved: 2476[Submit][Stat ...

  2. BZOJ 1061: [Noi2008]志愿者招募 [单纯形法]【学习笔记】

    1061: [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3975  Solved: 2421[Submit][Stat ...

  3. BZOJ-1061 志愿者招募 线性规划转最小费用最大流+数学模型 建模

    本来一眼建模,以为傻逼题,然后发现自己傻逼...根本没想到神奇的数学模型..... 1061: [Noi2008]志愿者招募 Time Limit: 20 Sec Memory Limit: 162 ...

  4. [BZOJ1061][Noi2008]志愿者招募

    [BZOJ1061][Noi2008]志愿者招募 试题描述 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难 题:为即将启动的奥运新项目招募一批短期志愿 ...

  5. bzoj 1061 志愿者招募(最小费用最大流)

    [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3792  Solved: 2314[Submit][Status][Di ...

  6. 【BZOJ】【1061】【NOI2008】志愿者招募

    网络流/费用流 OrzOrzOrz,这题太神了不会捉. 题解:https://www.byvoid.com/blog/noi-2008-employee/ 这道题正确的解法是构造网络,求网络最小费用最 ...

  7. BZOJ 1061: [Noi2008]志愿者招募 费用流

    1061: [Noi2008]志愿者招募 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1061 Description 申奥成功后,布布 ...

  8. bzoj1061: [Noi2008]志愿者招募

    线性规划与费用流.http://www.cnblogs.com/iiyiyi/p/5616080.html.数组范围开错了!!!然后2.31-1=0x7fffffff!=0x7f7f7f7f. 开始以 ...

  9. NOI2008 志愿者招募

    1061: [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1859  Solved: 1169[Submit][Stat ...

随机推荐

  1. POJ3616(KB12-R dp)

    Milking Time Time Limit: 1000MS    Memory Limit: 65536K Total Submissions: 9459  Accepted: 3935   De ...

  2. javax.net.ssl.SSLHandshakeException sun.security.validator.ValidatorException PK

    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building f ...

  3. Vue知识点(面试常见点)

    v-bind和v-model的区别 1.v-bind用来绑定数据和属性以及表达式,缩写为':' 2.v-model使用在表单中,实现双向数据绑定的,在表单元素外使用不起作用 什么是 mvvm? MVV ...

  4. jq插件写法

    如今做web开发,jQuery 几乎是必不可少的,同时jquery插件也是不断的被大家所熟知,以及运用.最近在搞这个jquery插件,发现它的牛逼之处,所以讲一讲jQuery插件的写法以及使用  (f ...

  5. windows与虚拟机的linux共享一个文件夹

    1.安装VMware Tools,在VMware面板上选择“虚拟机-重新安装VMware tools…” 2.使用命令 Ctrl+Alt+T 打开终端: 3.切换用户到root,命令 su 回车,输入 ...

  6. zigzag方式编码

    按以下公式转换: ParameterInteger = (value << 1) ^ (value >> 31) 参数值不支持大于pow(2,31) - 1或-1 * (pow ...

  7. 与HttpSession相关的监听器

    概述 与HttpSession相关的监听器有四个:分别是HttpSessionListener.HttpSessionAttributeListener.HttpSessionBindingListe ...

  8. WordCount系统分析与设计作业

    Gitee项目地址 https://gitee.com/gitdq/homework psp表 PSP2.1 PSP阶段 预估耗时 (分钟) 实际耗时 (分钟) Planning 计划 10 10 · ...

  9. Oracle EBS INV 查询物料无值 ECO

    查找物料的时候报错 没有输入值 解决方法: 针对FORM做trace 多查看几个生成的trace 搜索 MTL_SYSTEM_ITEMS_b 的信息 查看到最后面的语句(一般可直接查看) 看SQL 哪 ...

  10. AD账号解锁

    Get-ADUser -Filter * -Properties *  -SearchBase "dc=uxin,dc=youxinpai,dc=com"| ? {$_.locke ...