P4016 负载平衡问题

题目描述

GG 公司有 nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最少搬运量可以使 nn 个仓库的库存数量相同。搬运货物时,只能在相邻的仓库之间搬运。

输入格式

文件的第 11 行中有 11 个正整数 nn,表示有 nn 个仓库。

第 22 行中有 nn 个正整数,表示 nn 个仓库的库存量。

输出格式

输出最少搬运量。

输入输出样例

输入 #1复制

  1. 5
  2. 17 9 14 16 4

输出 #1复制

  1. 11

说明/提示

\(1<=n<=100\)

思路:

「问题分析」

转化为供求平衡问题,用最小费用最大流解决。

「建模方法」

首先求出所有仓库存货量平均值,设第i个仓库的盈余量为A[i],A[i] = 第i个仓库原有存货量 – 平均存货量。建立二分图,把每个仓库抽象为两个节点Xi和Yi。增设附加源S汇T。

1、如果A[i]>0,从S向Xi连一条容量为A[i],费用为0的有向边。

2、如果A[i]<0,从Yi向T连一条容量为-A[i],费用为0的有向边。

3、每个Xi向两个相邻顶点j,从Xi到Xj连接一条容量为无穷大,费用为1的有向边,从Xi到Yj连接一条容量为无穷大,费用为1的有向边。

求最小费用最大流,最小费用流值就是最少搬运量。

「建模分析」

计算出每个仓库的盈余后,可以把问题转化为供求问题。建立供求网络,把二分图X集合中所有节点看做供应节点,Y集合所有节点看做需求节点,在能一次搬运满足供需的Xi和Yj之间连接一条费用为1的有向边,表示搬运一个单位货物费用为1。另外还要在Xi与相邻的Xj之间连接边,表示货物可以暂时搬运过去,不立即满足需求,费用也为1。最大流满足了所有的盈余和亏损供求平衡,最小费用就是最少搬运量。

以上拷贝自:http://hzwer.com/1955.html 这位聚聚博主。

我的代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <cmath>
  6. #include <queue>
  7. #include <stack>
  8. #include <map>
  9. #include <set>
  10. #include <vector>
  11. #include <iomanip>
  12. #define ALL(x) (x).begin(), (x).end()
  13. #define sz(a) int(a.size())
  14. #define rep(i,x,n) for(int i=x;i<n;i++)
  15. #define repd(i,x,n) for(int i=x;i<=n;i++)
  16. #define pii pair<int,int>
  17. #define pll pair<long long ,long long>
  18. #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
  19. #define MS0(X) memset((X), 0, sizeof((X)))
  20. #define MSC0(X) memset((X), '\0', sizeof((X)))
  21. #define pb push_back
  22. #define mp make_pair
  23. #define fi first
  24. #define se second
  25. #define eps 1e-6
  26. #define gg(x) getInt(&x)
  27. #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
  28. #define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
  29. #define du2(a,b) scanf("%d %d",&(a),&(b))
  30. #define du1(a) scanf("%d",&(a));
  31. using namespace std;
  32. typedef long long ll;
  33. ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
  34. ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
  35. ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
  36. void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
  37. void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
  38. inline void getInt(int* p);
  39. const int maxn = 1000010;
  40. // const int inf = 0x3f3f3f3f;
  41. /*** TEMPLATE CODE * * STARTS HERE ***/
  42. const int MAX_N = 1000;
  43. const int MAX_M = 10000;
  44. const int inf = 0x3f3f3f3f;
  45. // int s, t;
  46. struct edge {
  47. int v, c, w, next; // v 表示边的另一个顶点,c 表示当前剩余容量,w 表示单位流量费用
  48. } e[MAX_M];
  49. int p[MAX_N], s, t, eid; // s 表示源点,t 表示汇点,需要在进行 costflow 之前设置完毕
  50. void init() {
  51. memset(p, -1, sizeof(p));
  52. eid = 0;
  53. }
  54. void insert(int u, int v, int c, int w) {
  55. e[eid].v = v;
  56. e[eid].c = c;
  57. e[eid].w = w;
  58. e[eid].next = p[u];
  59. p[u] = eid++;
  60. }
  61. void addedge(int u, int v, int c, int w) {
  62. insert(u, v, c, w);
  63. insert(v, u, 0, -w);
  64. }
  65. bool inq[MAX_N];
  66. int d[MAX_N]; // 如果到顶点 i 的距离是 0x3f3f3f3f,则说明不存在源点到 i 的最短路
  67. int pre[MAX_N]; // 最短路中连向当前顶点的边的编号
  68. bool spfa() { // 以源点 s 为起点计算单源最短路,如果不存在从 s 到 t 的路径则返回 false,否则返回 true
  69. memset(inq, 0, sizeof(inq));
  70. memset(d, 0x3f, sizeof(d));
  71. memset(pre, -1, sizeof(pre));
  72. d[s] = 0;
  73. inq[s] = true;
  74. queue<int> q;
  75. q.push(s);
  76. while (!q.empty()) {
  77. int u = q.front();
  78. q.pop();
  79. inq[u] = false;
  80. for (int i = p[u]; i != -1; i = e[i].next) {
  81. if (e[i].c) { //注意这个条件!!!spfa这里是以w求最短路的,但仍然不能忽略容量c的考虑!
  82. int v = e[i].v;
  83. if (d[u] + e[i].w < d[v]) {
  84. d[v] = d[u] + e[i].w;
  85. pre[v] = i;
  86. if (!inq[v]) {
  87. q.push(v);
  88. inq[v] = true;
  89. }
  90. }
  91. }
  92. }
  93. }
  94. return pre[t] != -1;
  95. }
  96. int min_cost_flow() { // 计算最小费用最大流
  97. int ret = 0; // 累加和
  98. while (spfa()) {
  99. int flow = inf;
  100. for (int i = t; i != s; i = e[pre[i] ^ 1].v) {
  101. flow = min(e[pre[i]].c, flow); // 计算当前增广路上的最小流量
  102. }
  103. for (int i = t; i != s; i = e[pre[i] ^ 1].v) {
  104. e[pre[i]].c -= flow; //容量是一定要跟着变化的,毕竟要继续循环使用spfa来更新下一条“能走的(看容量)”最短路。
  105. e[pre[i] ^ 1].c += flow;
  106. ret += e[pre[i]].w * flow;
  107. }
  108. }
  109. return ret;
  110. }
  111. int n;
  112. int a[MAX_N];
  113. int main()
  114. {
  115. //freopen("D:\\code\\text\\input.txt","r",stdin);
  116. //freopen("D:\\code\\text\\output.txt","w",stdout);
  117. init();
  118. du1(n);
  119. int sum = 0;
  120. repd(i, 1, n)
  121. {
  122. du1(a[i]);
  123. sum += a[i];
  124. }
  125. sum /= n;
  126. s = 0;
  127. t = n * 2 + 1;
  128. repd(i, 1, n)
  129. {
  130. a[i] -= sum;
  131. if (a[i] > 0)
  132. {
  133. addedge(s, i, a[i], 0);
  134. } else
  135. {
  136. addedge(i + n, t, -a[i], 0);
  137. }
  138. if (i - 1 > 0)
  139. {
  140. addedge(i, i + n - 1, inf, 1);
  141. addedge(i, i - 1, inf, 1);
  142. }
  143. if (i + 1 < n + 1)
  144. {
  145. addedge(i, i + n + 1, inf, 1);
  146. addedge(i, i + 1, inf, 1);
  147. }
  148. }
  149. addedge(1, n, inf, 1);
  150. addedge(1, n * 2, inf, 1);
  151. addedge(n, 1, inf, 1);
  152. addedge(n, 1 + n, inf, 1);
  153. printf("%d\n", min_cost_flow() );
  154. return 0;
  155. }
  156. inline void getInt(int* p) {
  157. char ch;
  158. do {
  159. ch = getchar();
  160. } while (ch == ' ' || ch == '\n');
  161. if (ch == '-') {
  162. *p = -(getchar() - '0');
  163. while ((ch = getchar()) >= '0' && ch <= '9') {
  164. *p = *p * 10 - ch + '0';
  165. }
  166. }
  167. else {
  168. *p = ch - '0';
  169. while ((ch = getchar()) >= '0' && ch <= '9') {
  170. *p = *p * 10 + ch - '0';
  171. }
  172. }
  173. }

P4016 负载平衡问题(最小费用最大流)的更多相关文章

  1. 洛谷P4016 负载平衡问题(最小费用最大流)

    题目描述 GG 公司有 nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 nn 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入输出格式 输入格 ...

  2. 洛谷 P4016负载平衡问题【费用流】题解+AC代码

    洛谷 P4016负载平衡问题 P4014 分配问题[费用流]题解+AC代码 负载平衡问题 题目描述 GG 公司有n个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n ...

  3. 洛谷P4016 负载平衡问题(费用流)

    传送门 嗯……完全不会……不过题解似乎讲的挺清楚…… 考虑一下,每一个仓库最终肯定都是平均数,所以数量大于平均数的可以往外运,小于平均数的要从别的地方运进来 考虑建一个超级源$S$和超级汇$T$,并把 ...

  4. 洛谷 P4016 负载平衡问题 【最小费用最大流】

    求出平均数sum,对于大于sum的点连接(s,i,a[i]-sum,0),表示这个点可以流出多余的部分,对于小于sum的点连接(i,t,sum-a[i],0)表示这个点可以接受少的部分,然后每个点向相 ...

  5. Libre 6013 「网络流 24 题」负载平衡 (网络流,最小费用最大流)

    Libre 6013 「网络流 24 题」负载平衡 (网络流,最小费用最大流) Description G 公司有n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使n ...

  6. LibreOJ #6013. 「网络流 24 题」负载平衡 最小费用最大流 供应平衡问题

    #6013. 「网络流 24 题」负载平衡 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  7. [CODEVS1916] 负载平衡问题(最小费用最大流)

    传送门 输入所有 a[i],求出平均值 sum,每个 a[i] -= sum 那么如果 a[i] > 0,从 s 向 i 连一条容量为 a[i] 费用为 0 的有向边 如果 a[i] < ...

  8. 【PowerOJ1754&网络流24题】负载平衡问题(费用流)

    题意: 思路: [问题分析] 转化为供求平衡问题,用最小费用最大流解决. [建模方法] 首先求出所有仓库存货量平均值,设第i个仓库的盈余量为A[i],A[i] = 第i个仓库原有存货量 - 平均存货量 ...

  9. P4016 负载平衡问题 网络流

    P4016 负载平衡问题 题目描述 GG 公司有 nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 nn个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运 ...

随机推荐

  1. Unity动态批处理和静态批处理学习

    本文转自:http://blog.csdn.net/lyh916/article/details/45725499,请点击链接查看楼主大神原文,尊重楼主版权. 参考链接:Unity圣典:http:// ...

  2. 用JavaScript来实现单例模式

    首先,了解一下什么是单例模式,这里我直接把菜鸟教程中的定义给copy过来: 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供 ...

  3. 《精通并发与Netty》学习笔记(06 - Apache Thrift使用简介)

    一.概述 Apache Thrift 是 Facebook 实现的一种高效的.支持多种编程语言的远程服务调用的框架.Thrift是由Facebook开发的,并在2008年捐给了Apache基金会,成为 ...

  4. Fabric docker-compose volumes配置解析

    chaincode: container_name: chaincode image: hyperledger/fabric-ccenv tty: true environment: - GOPATH ...

  5. Own MusicPlayer隐私策略

    本地音乐播放器 此为Own MusicPlayer本地音乐播放器的隐私策略,本隐私策略内容会不定期更新,以最新内容为主. 若您已经阅读并了解以下内容后,并继续使用该软件,即表示您已同意该协议. 访问权 ...

  6. 在vue项目中,将juery设置为全局变量

    1.首先执行:npm install  jQuery --save-dev,在package.json里加入jQuery. 2.修改build下的webpack.base.conf.js 方法一: 首 ...

  7. vue2.0 + npm + webpack 开发===环境配置

     cnpm安装:npm install -g cnpm --registry=http://registry.npm.taobao.org 1.安装vue-cli脚手架构建工具cnpm install ...

  8. 记录一次hadoop2.8.4版本RM接入zk ha问题

    背景: 公司将线上hadoop RM接入ZK 实现高可用 但ZK Znode 默认存储1M,当存储数据量大时候可能导致线上业务的崩溃 处理方案如下: 1,修改ZK配置 增加默认存储上限 2,修改RM数 ...

  9. Python 命名规范总结

    Python推荐命名规范: 模块名和包名采用小写字母并且以下划线分隔单词的形式: 如:browser_driver 类名或异常名采用每个单词首字母大写的方式: 如:BasePage, Keyboard ...

  10. 如何配置kindeditor的工具栏

    kindeditor编辑器的工具栏主要是指编辑器输入框上方的那些可以操作的菜单,默认情况下编辑器是给予了所有的工具栏.针对不同的用户,不同的项目,不同的环境,可能就需要保留部分工具栏.那么我们应该如何 ...