传说中的网络流24题之一,我刷的第二题菜。

据说这种东西做完了就可以有质的飞越?不过看着这些Luogu评级就有点蒙蔽。

首先我们看一下题目发现这不是均分纸牌的加强板吗,但是那个环的操作极大地限制了我的思想。

我们考虑用费用流求解。

首先拆点,把每一个仓库拆成两个,一个\(x_i\)表示供给别人的货物,一个\(y_i\)表示别人供给的货物。然后建立超级源点\(S\)和超级汇点\(T\)。

我们可以很容易地知道:每一个仓库最后剩下的货物数量必定是总货物数量的平均数

然后就很简单了。我们将所有的货物量\(a_i\)减去平均数,得到新的\(a_i\)。然后讨论:

  • 当\(a_i<0\)时,这个节点需要运入货物。所以我们呢将\(S\)与\(x_i\)相连,容量就是\(-a_i\),费用为\(0\)(至于为什么为\(0\)等下会解释)
  • 当\(a_i>0\)时,这个节点需要运出货物。所以我们呢将\(y_i\)与\(T\)相连,容量就是\(a_i\),费用为\(0\)

然后对于相邻节点还可以连边:

  • 将\(x_i\)与\(y_j\)相连,容量为\(\infty\),费用为\(1\)。这个很好理解吧,相邻的需要直接运输过去即可,费用就是运输量。
  • 将\(x_i\)与\(x_j\)相连,容量为\(\infty\),费用为\(1\)。这个还是要想一下的,相当于将\(x_i\)的货物暂时存放在\(x_j\)处,为其他的运输做准备。

然后由于所有的费用都在这些物体之间的运输中计算掉了,因此源汇点的费用就是\(0\)了。(其实也就是把那些供给的点连到一起方便跑而已,一个常见的技巧)

然后我们直接跑MCMF即可,然后引用一段著名的话:

最大流保证能够平衡货物,而最小费用流能保证运输的货物最少。

CODE

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=205,INF=2e9;
queue <int> q;
struct edge
{
int to,next,c,f;
}e[N<<3];
int head[N],dis[N],cap[N],a[N],pre[N],last[N],s,t,n,ave,cnt=-1;
bool vis[N];
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
inline int min(int a,int b)
{
return a<b?a:b;
}
inline void add(int x,int y,int c,int f)
{
e[++cnt].to=y; e[cnt].c=c; e[cnt].f=f; e[cnt].next=head[x]; head[x]=cnt;
}
inline void insert(int x,int y)
{
add(x,y,INF,1); add(y,x,0,-1); add(x,y+n,INF,1); add(y+n,x,0,-1);
}
inline bool SPFA(void)
{
memset(pre,-1,sizeof(pre));
memset(dis,63,sizeof(dis));
memset(cap,63,sizeof(cap));
memset(vis,0,sizeof(vis));
while (!q.empty()) q.pop();
q.push(s); vis[s]=1; dis[s]=0;
while (!q.empty())
{
int now=q.front(); q.pop(); vis[now]=0;
for (register int i=head[now];i!=-1;i=e[i].next)
if (e[i].c&&dis[e[i].to]>dis[now]+e[i].f)
{
dis[e[i].to]=dis[now]+e[i].f;
cap[e[i].to]=min(cap[now],e[i].c);
pre[e[i].to]=now; last[e[i].to]=i;
if (!vis[e[i].to]) vis[e[i].to]=1,q.push(e[i].to);
}
}
return pre[t]^-1;
}
inline void MCMF(void)
{
int tot=0;
while (SPFA())
{
tot+=cap[t]*dis[t]; int now=t;
while (now!=s)
{
e[last[now]].c-=cap[t];
e[last[now]^1].c+=cap[t];
now=pre[now];
}
}
printf("%d",tot);
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i; read(n); s=0,t=(n<<1)+1;
memset(head,-1,sizeof(head));
memset(e,-1,sizeof(e));
for (i=1;i<=n;++i)
read(a[i]),ave+=a[i]; ave/=n;
for (i=1;i<=n;++i)
{
a[i]-=ave; if (a[i]>0) add(s,i,a[i],0),add(i,s,0,0); else add(i+n,t,-a[i],0),add(t,i+n,0,0);
if (i==1) insert(1,n),insert(1,2); else
if (i==n) insert(n,1),insert(n,n-1); else insert(i,i-1),insert(i,i+1);
}
MCMF(); return 0;
}

Luogu P4016 负载平衡问题的更多相关文章

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

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

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

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

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

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

  4. P4016 负载平衡问题 网络流重温

    P4016 负载平衡问题 这个题目现在第二次做,感觉没有这么简单,可能是我太久没有写这种题目了,基本上都忘记了,所以我连这个是费用流都没有看出来. 有点小伤心,知道是费用流之后,我居然还拆点了. 这个 ...

  5. 洛谷P4016负载平衡

    题目 负载平衡问题是一个比较经典的网络流问题,但是该问题还有一个数学贪心法. 所以做这个题前,其实可以做一下均分纸牌问题. 均分纸牌问题 均分纸牌问题可以说是作为贪心的入门题. 做法 首先我们应当把原 ...

  6. (洛谷P2512||bzoj1045) [HAOI2008]糖果传递 || 洛谷P4016 负载平衡问题 || UVA11300 Spreading the Wealth || (洛谷P3156||bzoj3293) [CQOI2011]分金币

    bzoj1045 洛谷P4016 洛谷P2512 bzoj3293 洛谷P3156 题解:https://www.luogu.org/blog/LittleRewriter/solution-p251 ...

  7. 洛谷 [P4016] 负载平衡问题

    贪心做法 第一眼看见觉得和均分纸牌差不多,然而因为这是环形的,并不能用均分纸牌的方法做,但是均分纸牌的思想仍然适用 首先我们假设平均数为sum1. 那么对于第1个人,我们假设他给第N个人K个糖果, 第 ...

  8. 『题解』洛谷P4016 负载平衡问题

    title: categories: tags: - mathjax: true --- Problem Portal Portal1:Luogu Portal2: LibreOJ Descripti ...

  9. P2512 [HAOI2008]糖果传递&&P3156 [CQOI2011]分金币&&P4016 负载平衡问题

    P2512 [HAOI2008]糖果传递 第一步,当然是把数据减去平均数,然后我们可以得出一串正负不等的数列 我们用sum数组存该数列的前缀和.注意sum[ n ]=0 假设为链,那么可以得出答案为a ...

随机推荐

  1. 网络基础 Windows控制台下Ftp使用简介

    Windows控制台下Ftp使用简介 by:授客 QQ:1033553122 测试环境: ftp服务器所在主机ip:172.25.75.2 ftp用户目录:F:\ftp   C:\Users\laif ...

  2. 2018下半年Android面试历程

    个人看法:可以总结下他的面试经历以及涉及到的面试题 下面开始正文吧: 从今年下半年以来就开始在杭州准备简历找工作了,原因基本都懂的,没多少工资,投递简历的渠道是Boss,偶尔也在拉钩上投递,刚开始把简 ...

  3. 前端路由简介以及vue-router实现原理

    后端路由简介 路由这个概念最先是后端出现的.在以前用模板引擎开发页面时,经常会看到这样 http://www.xxx.com/login 大致流程可以看成这样: 浏览器发出请求 服务器监听到80端口( ...

  4. Video.js web视频播放器

    免费视频播放器videojs中文教程 Video.js是一款web视频播放器,支持html5和flash两种播放方式.更多关于video.js的介绍,可以访问官方网站介绍,我之前也写过一篇关于vide ...

  5. 【第四篇】SAP ABAP7.5x新语法之CREATE DATA&INTERFACE

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文地址:SAP ABAP7.5x系列之CREATE DA ...

  6. 对Spring的理解(简单)!

    1.Spring是对j2EE诸多功能进行封装了的一个工具集:它的核心就是提供了一种新的机制来管理业务对象及依赖关系:具体就是控制反转.依赖注入,Aop(面向切面). Spring的底层实现机制是用De ...

  7. .net core HttpContext(Http上下文)

    在.NET Core中,只有Controller才能直接使用 HttpContext ,其他地方需要通过HttpContextAccessor来访问

  8. 常用Linux 服务器命令--各种性能指标命令

    如果你想知道你的服务器正在做干什么,你就需要了解一些基本的命令,一旦你精通了这些命令,那你就是一个专业的 Linux 系统管理员. 监控命令## iostat### iostat命令用来显示存储系统的 ...

  9. 如何快速搭建&配置本地服务器-前端技能

    废话不多说,上图: 首先登录http://www.phpstudy.net/download.html 下载安装phpstudy,特别简单不详解: 创建一个本机项目并且与本机域名进行绑定主要分为两步; ...

  10. CMD(命令提示符)命令大全及网络安全课程中所用到的命令

    CMD命令大全详解: 1.arp -a 获得IP地址,MAC地址. 2.arp -d * 命令用于清空arp缓存表. 3.arp –s 网关IP 网关MAC 命令则是将网关IP地址与其相应的MAC地址 ...