1003 NOIP 模拟赛Day2 城市建设
题面不好找放一个吧。
Description
描述
在有$N$个地级市的H省,政府为了城市开发建设,决定先修路,后造房子,以吸引外来人员。一开始每个城市中有$b_i$个住户,而在两个城市$u,v$之间建路需要的代价就是$R$乘以$u,v$两个城市的住户数目之和。建路的目标是使得所有城市相互之间都可达。
建完路之后,就要造房子了,由于$H$省的房产商仅有一家,所以只能一户一户的造房子。不过政府有权利任意安排建造的顺序,在城市i建造一个房子的代价是,$h_i$乘以城市i当前住户数目同城市i周边城市(即通过道路直接相连的)的当前住户数目之和。由于现在房子炙手可热,所以每造好一户,就立刻有用户入住。政府决定最后的目标是每个城市$a_i$个住户。作为政府部门的财务主管,请你计算出最少需要花费多少钱,才可以完成上述要求。
输入格式
第一行一个整数$N$,表示有$N$个城市;
接下来一行有$N$个整数,描述$b$数组,也就是每个城市一开始的住户数;
接下来一行有$N$个整数,描述$a$数组,也就是每个城市最终的住户数;
接下来一行有$N$个整数,描述$h$数组,表示建房费用;
接下来有一个$N*N$的矩阵,第$i$行第$j$个元素表示原来$i$城市和$j$城市是否有路相连。
最后一行一个整数$R$,表示建路的费用。
输出格式
一个整数,表示最小费用。
数据范围与约定
- 对于$100\%$ 的数据,$1 \leq N \leq 50$,$ b[i] \leq a[i] \leq 100000$,$h[i], R \leq 100000$,矩阵是对称的。
Solution
首先思考一个结论,假设有城市$x, y$,对应$b_x,b_y,h_x,h_y$,需要在这两个城市各建若干个房子,那么我们一个一个城市分别完成一定比交错完成优。
证明:
假设$h_x > h_y$,那么先在$x$建应当比在$y$建优,如果每一个城市都只要建两所房子的话,列出式子:
$h_x(b_x + b_y) + h_y(b_x + b_y + 1) + h_x(b_x + b_y + 2) + h_y(b_x + b_y + 3)$
$h_x(b_x + b_y) + h_x(b_x + b_y + 1) + h_y(b_x + b_y + 2) + h_y(b_x + b_y + 3)$
后者减去前者,约掉同类项:
有 $(2h_y + h_x) - (h_y + 2h_x) = h_y - h_x < 0$成立。
需要建两个房子以上的时候可以归纳。
合在一起不好算,我们考虑拆开计算贡献,对于每一个点$x$,它对答案的贡献是$h_x(b_x + (b_x + 1) + (b_x + 2) + ... + (a_x - 1)) + h_x * (sum(y))$ $y$是$x$能直接联通的点。
前面是一个等差数列求和,后面我们枚举所有的边来计算。
按照之前得到的结论,我们对于一条存在的边$(i, j)$,如果$h_i > h_j$就先把$i$的房子建完再把$j$的房子建完,否则就先建$j$。
把已知的边算完之后还要联通可能不连通的若干个联通块,这时候就可以把连边的代价计算到边权里面去做一个最小生成树,$kruskal$轻松跑过。
时间复杂度是跑不满的$O(n^2logn)$,然而$n$的大小非常具有迷惑性。
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll; const int N = ;
const int M = ; int n, cnt = , w[N][N], ufs[N];
ll a[N], b[N], c, h[N]; struct Pathway {
int u, v;
ll val; inline Pathway(int nowU = , int nowV = , ll nowVal = 0LL) {
u = nowU, v = nowV, val = nowVal;
} friend bool operator < (const Pathway &x, const Pathway &y) {
return x.val < y.val;
} } path[M]; template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > ''|| ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline void init() {
for(int i = ; i <= n; i++) ufs[i] = i;
} int find(int x) {
return x == ufs[x] ? x : ufs[x] = find(ufs[x]);
} int main() {
read(n);
for(int i = ; i <= n; i++) read(b[i]);
for(int i = ; i <= n; i++) read(a[i]);
for(int i = ; i <= n; i++) read(h[i]); char s[N];
for(int i = ; i <= n; i++) {
scanf("%s", s + );
for(int j = ; j <= n; j++)
if(s[j] == 'Y') w[i][j] = ;
else w[i][j] = ;
}
read(c); ll ans = 0LL; int eCnt = ;
init();
for(int i = ; i <= n; i++)
for(int j = ; j < i; j++) {
if(w[i][j]) {
if(h[i] < h[j]) ans += h[j] * b[i] * (a[j] - b[j]) + h[i] * a[j] * (a[i] - b[i]);
else ans += h[i] * b[j] * (a[i] - b[i]) + h[j] * a[i] * (a[j] - b[j]); int u = find(i), v = find(j);
if(u == v) continue;
ufs[u] = v;
++eCnt;
} else {
if(h[i] < h[j]) path[++cnt] = Pathway(i, j, h[j] * b[i] * (a[j] - b[j]) + h[i] * a[j] * (a[i] - b[i]) + (b[i] + b[j]) * c);
else path[++cnt] = Pathway(i, j, h[i] * b[j] * (a[i] - b[i]) + h[j] * a[i] * (a[j] - b[j]) + (b[i] + b[j]) * c);
}
} sort(path + , path + + cnt);
for(int i = ; i <= cnt && eCnt < n - ; i++) {
int u = find(path[i].u), v = find(path[i].v);
if(u == v) continue;
ans += path[i].val;
ufs[u] = v;
++eCnt;
} for(int i = ; i <= n; i++)
ans += h[i] * (a[i] - b[i]) * (b[i] + a[i] - ) / ; printf("%lld\n", ans);
return ;
}
1003 NOIP 模拟赛Day2 城市建设的更多相关文章
- CH Round #58 - OrzCC杯noip模拟赛day2
A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...
- CH Round #49 - Streaming #4 (NOIP模拟赛Day2)
A.二叉树的的根 题目:http://www.contesthunter.org/contest/CH%20Round%20%2349%20-%20Streaming%20%234%20(NOIP 模 ...
- CH Round #55 - Streaming #6 (NOIP模拟赛day2)
A.九九归一 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2355%20-%20Streaming%20%236%20(NOIP模拟赛day2)/九九归一 题 ...
- CH Round #55 - Streaming #6 (NOIP模拟赛day2)解题报告
T1九九归一 描述 萌蛋在练习模n意义下的乘法时发现,总有一些数,在自乘若干次以后,会变成1.例如n=7,那么5×5 mod 7=4,4×5 mod 7=6,6×5 mod 7=2,2×5 mod 7 ...
- 2016.10.30 NOIP模拟赛 day2 PM 整理
满分:300分 直接全部爆零,真的是很坑啊! 10.30的题目+数据:链接:http://pan.baidu.com/s/1jHXLace 密码:i784 T1: 题目中的难点就是每次折叠的点可能应经 ...
- 2016.10.30 NOIP模拟赛 day2 AM 整理
题目+数据:链接:http://pan.baidu.com/s/1gfBg4h1 密码:ho7o 总共得了:130分, 1:100分 2:30分(只会这30分的暴力) 3:0(毫无思路) 虽然不高, ...
- CH Round #55 - Streaming #6 (NOIP模拟赛day2)(被虐哭)
http://ch.ezoj.tk/contest/CH%20Round%20%2355%20-%20Streaming%20%236%20%28NOIP%E6%A8%A1%E6%8B%9F%E8%B ...
- 【2018.10.18】noip模拟赛Day2 地球危机(2018年第九届蓝桥杯C/C++A组省赛 三体攻击)
题目描述 三体人将对地球发起攻击.为了抵御攻击,地球人派出了 $A × B × C$ 艘战舰,在太 空中排成一个 $A$ 层 $B$ 行 $C$ 列的立方体.其中,第 $i$ 层第 $j$ 行第 $k ...
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
随机推荐
- hdoj-1037-Keep on Truckin'(水题)
题目链接 /* 题意:三个通道,如果比168低,那么过不去,输出最先碰到的低的通道高度值 */ #include <iostream> using namespace std; int ...
- linux shell 学习笔记--内部命令学习
.基本命令 新手必须要掌握的初级命令 ls 基本的列出所有文件的命令.但是往往就是因为这个命令太简单,所以我们总是低估它.比如 ,用 -R 选项,这是递归选项,ls 将会以目录树的形式列出所有文件, ...
- Redis底层探秘(五):Redis对象
前面几篇文章,我们一起学习了redis用到的所有主要数据结构,比如简单动态字符串(sds).双端链表.字典.压缩列表.整数集合等等. redis并没有直接使用这些数据结构来实现键值对数据库,而是基于这 ...
- Hat’s Words(字典树的运用)
个人心得:通过这道题,对于树的运用又加深了一点,字典树有着他独特的特点,那个指针的一直转换着实让我好生想半天, 不得不佩服这些发明算法人的大脑. 这题的解决方法还是从网上找到的,还好算法是自己实现得, ...
- JS计算字符串的长度
最近项目上经常要用到计算字符串的长度的问题,有时需要按照byte进行计算长度,所以我就想在页面上用js实现,于是就到网上查了相关的资料,发现确实有很多的版本,这里给出两个比较好用的. //方法一:逐个 ...
- python list和元祖
一,元祖 在python中元祖是只能查询和读取的一组数据,在()内的赋值就是元祖,只有查询和读取的功能: 1.len()方法:查询元祖有多少个元素 s = (') print(len(s)) 结果: ...
- Operating System-进程间互斥的问题-生产者&&消费者引入
之前介绍的几种解决进程间互斥的方案,不管是Peterson方案还是TSL指令的方式,都有一个特点:当一个进程被Block到临界区外面时,被Block的进程会一直处于忙等待的状态,这个不但浪费了CPU资 ...
- jQuery判断 form表单提交时一些文本框的判断
一: form表单提交时如果表单里有input标签为空那么不提交form表单. <head> <script type="text/javascript"> ...
- POJ1020(小正方形铺大正方形)
Anniversary Cake Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 16579 Accepted: 5403 ...
- [转载]PCI/PCIe基础——配置空间
转载地址:http://blog.csdn.net/jiangwei0512/article/details/51603525 PCI/PCIe设备有自己的独立地址空间,这部分空间会映射到整个系统的地 ...