【bzoj1150】[CTSC2007]数据备份Backup 模拟费用流+链表+堆
题目描述
你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份。然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏的乐趣。已知办公楼都位于同一条街上。你决定给这些办公楼配对(两个一组)。每一对办公楼可以通过在这两个建筑物之间铺设网络电缆使得它们可以互相备份。然而,网络电缆的费用很高。当地电信公司仅能为你提供 K 条网络电缆,这意味着你仅能为 K 对办公楼(或总计2K个办公楼)安排备份。任一个办公楼都属于唯一的配对组(换句话说,这 2K 个办公楼一定是相异的)。此外,电信公司需按网络电缆的长度(公里数)收费。因而,你需要选择这 K 对办公楼使得电缆的总长度尽可能短。换句话说,你需要选择这 K 对办公楼,使得每一对办公楼之间的距离之和(总距离)尽可能小。下面给出一个示例,假定你有 5 个客户,其办公楼都在一条街上,如下图所示。这 5 个办公楼分别位于距离大街起点 1km, 3km, 4km, 6km 和 12km 处。电信公司仅为你提供 K=2 条电缆。

输入
输入的第一行包含整数n和k,其中n(2 ≤ n ≤100 000)表示办公楼的数目,k(1≤ k≤ n/2)表示可利用的网络电缆的数目。接下来的n行每行仅包含一个整数(0≤ s ≤1000 000 000), 表示每个办公楼到大街起点处的距离。这些整数将按照从小到大的顺序依次出现。
输出
输出应由一个正整数组成,给出将2K个相异的办公楼连成k对所需的网络电缆的最小总长度。
样例输入
5 2
1
3
4
6
12
样例输出
4
题解
模拟费用流+链表+堆
本题正常题解应该是“贪心+堆”,但自从某次集训get到了模拟费用流的思想后,用在这道题里是再恰当不过了。
先前缀相减得到相邻两建筑物之间的距离,然后想到dp,但是MLE+TLE;考虑如果是费用流的话,该怎样建图?
(边权中第一个为容量,第二个为费用)
那么考虑EK费用流的过程:先选择一条最短路,加入到答案,然后将路径上的边容量-1,反向边容量+1。
那么我们模拟这个过程:
首先找到SS->S->3->2->T这条最短路,然后把它路径上的边容量-1,反向边容量+1,得到下图:
(受到画图软件的限制,只能画成这个样子,如果在草纸上推的话直接将原来的正向边反过来就行)
这个时候我们会发现3->S、T->2这两条反向边是没有用处的,所以直接删掉就好。
(再次尴尬)
这回我们发现,1->2、反向边2->3、3->4可以合并成一条新的边1->4,费用为2-1+2。
那么就可以在原图中把1->2、3->2、3->4的边都删了,再加上1->4的边。
使用链表实现这个过程,并用堆维护最小费用。删除什么的,对边打个标记就好了。
最后不断选出边加到答案中,最后得到的就是最小费用了。
时间复杂度$O(n\log n)$。
注意:如果选出的边是边界上的边(如1->2),那么不能进行加边操作,但是必须进行删边操作(和2相连的不能再选)
代码细节挺多
#include <cstdio>
#include <cstring>
#include <queue>
#include <utility>
#define N 100010
using namespace std;
priority_queue<pair<int , int> > q;
int tot , d[N] , last[N << 1] , next[N << 1] , val[N << 1];
bool del[N << 1];
int main()
{
int n , k , i , u , ans = 0;
scanf("%d%d" , &n , &k);
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &d[i]);
for(i = 2 ; i < n ; i ++ ) last[i] = i - 1;
for(i = 1 ; i < n - 1 ; i ++ ) next[i] = i + 1;
for(i = 1 ; i < n ; i ++ ) val[i] = d[i + 1] - d[i] , q.push(make_pair(-val[i] , i));
tot = n - 1;
while(k -- )
{
while(del[q.top().second]) q.pop();
u = q.top().second , q.pop() , ans += val[u] , del[u] = del[last[u]] = del[next[u]] = 1 , next[last[u]] = last[next[u]] = 0;
if(!last[u]) last[next[next[u]]] = 0;
else if(!next[u]) next[last[last[u]]] = 0;
else
{
val[++tot] = val[last[u]] + val[next[u]] - val[u] , last[tot] = last[last[u]] , next[tot] = next[next[u]];
if(last[tot]) next[last[tot]] = tot;
if(next[tot]) last[next[tot]] = tot;
q.push(make_pair(-val[tot] , tot));
}
}
printf("%d\n" , ans);
return 0;
}
【bzoj1150】[CTSC2007]数据备份Backup 模拟费用流+链表+堆的更多相关文章
- BZOJ1150[CTSC2007]数据备份Backup——模拟费用流+堆+链表
题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游 ...
- BZOJ1150 [CTSC2007]数据备份Backup 链表+小根堆
BZOJ1150 [CTSC2007]数据备份Backup 题意: 给定一个长度为\(n\)的数组,要求选\(k\)个数且两两不相邻,问最小值是多少 题解: 做一个小根堆,把所有值放进去,当选择一个值 ...
- bzoj1150 [CTSC2007]数据备份Backup 双向链表+堆
[CTSC2007]数据备份Backup Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2727 Solved: 1099[Submit][Stat ...
- BZOJ1150 [CTSC2007] 数据备份Backup 贪心_堆_神题
Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家 ...
- BZOJ1150 [CTSC2007]数据备份Backup 【堆 + 链表】
题目 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏的 ...
- BZOJ1150 [CTSC2007]数据备份Backup 贪心 堆
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1150 题意概括 数轴上面有一堆数字. 取出两个数字的代价是他们的距离. 现在要取出k对数,(一个数 ...
- bzoj1150: [CTSC2007]数据备份Backup
题目大意: 在n个点中,选出k对相邻的互不相同的点,使k段距离的总和最小. 贪心,双向链表. 首先,点之间的距离是动态的,所以要用堆来维护. 每次都选择最近的点.但因为其他情况,可能最终不会选择这 ...
- BZOJ2151种树——模拟费用流+链表+堆
题目描述 A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树.园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n.并且每个位置都有一个美观度Ai,如果在这 ...
- BZOJ3502PA2012Tanie linie&BZOJ2288[POJ Challenge]生日礼物——模拟费用流+链表+堆
题目描述 n个数字,求不相交的总和最大的最多k个连续子序列. 1<= k<= N<= 1000000. 输入 输出 样例输入 5 2 7 -3 4 -9 5 样例输出 13 根据 ...
随机推荐
- spingMVC异步上传文件
框架是个强大的东西,一般你能想到的,框架都会帮你做了,然后只需要会用就行了,spingmvc中有处理异步请求的机制,而且跟一般处理请求的方法差别不大,只是多了一个注解:spingmvc也可以将stri ...
- luogu p1652 圆
题目部分 题目描述 给出N个圆,保证任意两个圆都相离,然后给出两个点(x1,y1).(x2,y2),保证均不在某个圆上,要从点(x1,y1)到(x2,y2)画条曲线,问这条曲线最少穿过多少次圆的边界? ...
- 北京教育软件创业公司招 .net工程师
北京教育软件创业公司,招 .net工程师,月工资2万左右,有合适的朋友帮忙推荐下,要求水平稍高一些的.产品目前用Winform开发的.创始人两个清华,一个北大.老板在美国待了七年回来的,爱人在清华教书 ...
- configure: error: cannot guess build type; you must specify one解决方法
原文地址:https://blog.csdn.net/hebbely/article/details/53993141 1.configure: error: cannot guess build t ...
- 提取PPT文件中的Vba ProjectStg Compressed Atom。Extract PPT VBA Compress Stream
http://msdn.microsoft.com/en-us/library/cc313106(v=office.12).aspx 微软文档 PartI ********************* ...
- 关于 pip安装的可能错误的排除
今天安装selenium总是报错(下为错误信息) C:\Python27\Scripts>pip install seleniumCollecting seleniumC:\Python27\l ...
- scrapy之五大核心组件
scrapy之五大核心组件 scrapy一共有五大核心组件,分别为引擎.下载器.调度器.spider(爬虫文件).管道. 爬虫文件的作用: a. 解析数据 b. 发请求 调度器: a. 队列 队列是一 ...
- Notepad++远程连接Linux系统
首先在官网下载 https://notepad-plus-plus.org/news/notepad-7.6.4-released.html 在命令行数输入ifconfig 查看自己的Linux的ip ...
- 【学习总结】C-翁恺老师-入门-第3周<循环>
[学习总结]C-翁恺老师-入门-总 1-求一个整数的位数:引入循环while 注:循环体内要有改变循环的机会,要不然就死循环了啊! 注:手写推测程序是否正确. 注:测试程序-边界:个位数.10.0.负 ...
- Linux查看和注销用户(User)
Linux如何注销其他用户?_Linux教程_Linux公社-Linux系统门户网站https://www.linuxidc.com/Linux/2012-07/64939.htm linux注销指定 ...