[bzoj3455]供电网络
来源:互联网 发布:海岛奇兵菊花升级数据 编辑:程序博客网 时间:2024/04/27 00:13
题目描述
阿狸和桃子居住的世界里, 只有一个国家, 这个国家有很多城市, 每个城市直接由中央政府管辖.
电力是这个国家的唯一能源, 但是每个城市的发电能力都不一样, 于是就产生了某些城市电力不足, 而某些城市却电力过剩的情况.
阿狸作为国家的首席工程师, 阿狸的一项重要工作就是均衡整个国家的电力, 使得每个城市的电力都恰好没有剩余或不足.
好在一些城市之间有电线可以输送电力, 这些电线都有自己的输送上限和下限, 并且输送电力的同时会产生大量的热.
每条电线i 发出的热量一定是关于输送电量的一个没有常数项的二次函数,即a_i*x^2+b_i*x, 并且由于电线是二极管做成的, 很显然只能单向输送电力. 每单位热量需要用1 单位的金币来冷却. 任何两个城市之间, 至多有一条电线.
不幸的是, 有时电力网络不像我们想的那么完美, 某些情况下可能无论如何都不能满足整个国家的电力需求. 这种情况下就只好向别的世界购买电力或者将电力输出给别的世界(注意, 每个城市的电力不能有剩余!), 每个城市买入或者输出电力的价格是不一样的(输出也要花钱).
由于阿狸的国家没有小数的概念, 输送,、购买或者交换电力都必须是以整数1 为单位.
阿狸的任务是最小化金币的花费(买入/送出的费用+电线上发热的冷却费用),他最近被这个问题搞得焦头烂额, 以至于没有时间去陪桃子玩, 结果天天被桃子骂T_T. 好在有你, 万能的程序猿, 请你编写一个程序来帮阿狸解决这个问题吧.
最小费用可行流
建图显然:
每个城市建一个点,如果富余j的电量s向i连下限j上限j费用0的边,如果缺失j的电量i向t连下限j上限j费用0的边。向外国买电,s向i连下限0上限inf费用为买电费用的边,向外国送电,i向t连下限0上限inf费用为送电费用的边。对于输电线u向v,是一个凸费用边。一般凸费用边ax^2+bx,上限为L,我们都习惯拆为L条边,容量均为1,费用分别为a+b,3a+b,5a+b……而本题还有下限,u到v下限为拆边方法见我的上下界网络流学习小计,所以ss到v也要连一条凸费用的边,然后u到v的边容量变成r-l了,然而其的费用不是从a+b开始的。所以实现时,每条边保存初始费用以及增减系数(注意是增减系数而不是二次项系数,因为反向弧和正向弧的增减系数是一样的,可以自己思考一下为什么),每次一条边容量-1时,其费用就加上两倍的增减系数,类似容量+1时其费用就减去两倍的增减系数。然后所有的边都能表示为凸费用边的形式(即使其费用函数是一次函数或常数函数),然后这样的实现其实就是动态加边。但是要注意一下反向弧的初始费用以及ss到v的初始费用。详见代码。
然后就是求最小费用可行流了,相当于ss到tt跑最小费用最大流,这里最大流的限制是针对满足下限的,而原图没有流量限制,所以不会出现一个城市不断向外国买电然后向外国送电的情况(简单来说,买电和送电不是必须的,他们下限为0,原图最大流为无穷大,而新图不需要满足他们的流量限制,因为新图最大流不对应原图最大流)
还有一种做法,是把有下限的边的费用拉得很小,按照最小费用的限制就会被强制跑,然后用spfa(zkw不能处理正向弧为负费用的情况)增广直的费用》0。由于我没打过,这里不多说。
#include<cstdio>#include<iostream>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=200+10,maxm=(600+maxn*3)*2*3+10,inf=1000000000;int h[maxn],now[maxn],d[maxn],go[maxm],next[maxm],dis[maxm],L[maxm],co[maxm],fx[maxm],ax[maxm];bool bz[maxn],czy;int i,j,k,l,r,u,v,s,t,n,m,tot,ans,ss,tt,tmp;void add(int x,int y,int z,int c,int a,int d){ go[++tot]=y; dis[tot]=z; co[tot]=c; ax[tot]=a; fx[tot]=tot+d; next[tot]=h[x]; h[x]=tot;}void link(int x,int y,int l,int r,int a,int b){ add(ss,y,l,a+b,a,1); add(y,ss,0,a-b,a,-1); add(x,tt,l,0,0,1); add(tt,x,0,0,0,-1); add(x,y,r-l,(2*l+1)*a+b,a,1); add(y,x,0,(1-2*l)*a-b,a,-1);}int dfs(int x,int cost){ bz[x]=1; if (x==tt){ ans+=cost; return 1; } int r=now[x]; while (r){ if (!bz[go[r]]&&dis[r]&&d[x]==d[go[r]]+co[r]){ if (dfs(go[r],cost+co[r])){ dis[r]--; co[r]+=2*ax[r]; dis[fx[r]]++; co[fx[r]]-=2*ax[fx[r]]; now[x]=r; return 1; } } r=next[r]; } now[x]=0; return 0;}bool change(){ int tmp=inf,i,r; fo(i,ss,tt) if (bz[i]){ r=h[i]; while (r){ if (!bz[go[r]]&&dis[r]&&d[go[r]]+co[r]-d[i]<tmp) tmp=d[go[r]]+co[r]-d[i]; r=next[r]; } } if (tmp==inf) return 0; fo(i,ss,tt) if (bz[i]) d[i]+=tmp; return 1;}int main(){ scanf("%d%d",&n,&m); ss=1;tt=n+4; s=2;t=n+3; fo(i,1,n){ scanf("%d%d%d",&j,&k,&l); if (j>0) link(s,i+2,j,j,0,0);else link(i+2,t,-j,-j,0,0); link(s,i+2,0,inf,0,k); link(i+2,t,0,inf,0,l); } fo(i,1,m){ scanf("%d%d%d%d%d%d",&j,&k,&l,&r,&u,&v); link(j+2,k+2,u,v,l,r); } link(t,s,0,inf,0,0); do{ fo(i,ss,tt) now[i]=h[i]; fill(bz+ss,bz+tt+1,0); while (dfs(ss,0)) fill(bz+ss,bz+tt+1,0); }while (change()); printf("%d\n",ans);}
- [bzoj3455]供电网络
- 电池供电网络摄像机方案
- 【集训队互测2013】供电网络
- 德州仪器带来永续供电的无线传感器网络
- 通宵供电
- 无线供电
- MHL供电
- UPS供电
- PoE供电、集中供电、点对点供电各自的优缺点
- 供电GIS的特征
- 远程供电交换机
- 单片机的供电
- PoE供电应用研究
- 以太网 PoE 供电交换机
- 电池供电原理
- 无线供电技术
- mini2440 3.7v供电
- W5100供电问题
- Android自学之路
- ARM-LINUX 交叉编译工具链搭建
- github 详解详解
- 《Hadoop:The Definitive Guide 4th Edition》Chapter 1 Meet Hadoop
- ts
- [bzoj3455]供电网络
- 自定义cell
- Servlet生命周期
- 51单片机data,idata,xdata,pdata的区别
- iOS复制链接到剪贴板
- neuq oj 1038: 谭浩强C语言(第三版)习题4.8 C语言
- Redis教程(十二):服务器管理命令总结
- Java byte数据类型详解
- ts