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 ...
随机推荐
- 从jQuery学细节
前言 最近看了两遍jQuery源码,感觉只是看懂了jQuery的小部分小部分,不过仅此,就已经对john resig佩服的五体投地咯.. 下面附上这位帅哥的靓照,记住吧,是他改变了世界. 看的大多是实 ...
- 1.Linux和Unix区别
整理来源于网络:http://blog.csdn.net/xiaojianpitt/article/details/6377419 有很多初学Linux的人比较关心Linux和windows的区别,这 ...
- Investment(完全背包)
个人心得:炸了炸了,这背包什么的脑阔痛. 完全背包什么鬼咯,状态正向转移与01背包正好相反. 二维数组的状态转移. 一维数组的优化,注意正向覆盖. 本题中的思想 ;y<=year;y++){ ; ...
- 滑雪(经典DP思想)
个人心得:思想还是不够,开始自己写但是不知道如何记录长度,也不太知道状态的转移,后面看了百度, 发现人人为我我为人人就是一步一步推导, 而递归思想就要求学会记录和找到边界条件,这一题中的话就是用递归, ...
- 下载安装tomcat至服务器
1.安装JDK之后,下载Tomcat:http://tomcat.apache.org/download-70.cgi选择下载32-bit/64-bit Windows Service Install ...
- bzoj 3527 [Zjoi2014]力——FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3527 把 q[ i ] 除掉.设 g[ i ] = i^2 ,有一半的式子就变成卷积了:另一 ...
- BZOJ3403:[USACO2009OPEN]Cow Line
浅谈队列:https://www.cnblogs.com/AKMer/p/10314965.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php?i ...
- Python collections系列之双向队列
双向队列(deque) 一个线程安全的双向队列 1.创建一个双向队列 import collections d = collections.deque() d.append(') d.appendle ...
- java从键盘输入数,分解质因数,
总结:1.break;的用法 当最小质因数不能被输入的值整除时,需要继续循环.k++. 当然输入的数,本身就是质数时,那么 package com.b; import java.util.Scanne ...
- 侯捷STL学习(12)--STL相关内容hash+tuple
layout: post title: 侯捷STL学习(12) date: 2017-08-01 tag: 侯捷STL --- 第四讲 STL相关的内容 Hash Function 将hash函数封装 ...