2001: [Hnoi2010]City 城市建设

Time Limit: 20 Sec  Memory Limit: 162 MB
Submit: 1132  Solved: 555
[Submit][Status][Discuss]

Description

PS国是一个拥有诸多城市的大国,国王Louis为城市的交通建设可谓绞尽脑汁。Louis可以在某些城市之间修建道路,在不同的城市之间修建道路需要不同的花费。Louis希望建造最少的道路使得国内所有的城市连通。但是由于某些因素,城市之间修建道路需要的花费会随着时间而改变,Louis会不断得到某道路的修建代价改变的消息,他希望每得到一条消息后能立即知道使城市连通的最小花费总和, Louis决定求助于你来完成这个任务。

Input

文件第一行包含三个整数N,M,Q,分别表示城市的数目,可以修建的道路个数,及收到的消息个数。 接下来M行,第i+1行有三个用空格隔开的整数Xi,Yi,Zi(1≤Xi,Yi≤n, 0≤Zi≤50000000),表示在城市Xi与城市Yi之间修建道路的代价为Zi。接下来Q行,每行包含两个数k,d,表示输入的第k个道路的修建代价修改为d(即将Zk修改为d)。

Output

输出包含Q行,第i行输出得知前i条消息后使城市连通的最小花费总和。

Sample Input

5 5 3
1 2 1
2 3 2
3 4 3
4 5 4
5 1 5
1 6
1 1
5 3

Sample Output

14
10
9

HINT

【数据规模】 对于20%的数据, n≤1000,m≤6000,Q≤6000。 有20%的数据,n≤1000,m≤50000,Q≤8000,修改后的代价不会比之前的代价低。 对于100%的数据, n≤20000,m≤50000,Q≤50000。

Source

 

[Submit][Status][Discuss]

十分懵逼的一道CDQ分治。

solve(l,r) 解决l到r区间内的修改及询问。

边界:l==r,可以直接做最小生成树得到答案。

其他:递归之前,需要在当前层进行两个操作:

contraction 求出所有的必须边,并直接把必须边加入答案,之后不再考虑;顺道把必须边连接的两点永久合并。

reduction 求出所有的不可能边,并直接把不可能边删除,之后不再考虑。

把所有待修改的边权值设为-inf,做最小生成树,在MST上的非待修改边都是必须边。

把所有待修改的边权值设为+inf,做最小生成树,不在MST上的非待修改边都是不可能边。

进行两个操作之后,图的规模会缩小,也许是缩小一半,不造,这个太玄学,大爷都不会。

 #include <bits/stdc++.h>

 inline int getC(void) {
static const int siz = ; static char buf[siz];
static char *hd = buf + siz;
static char *tl = buf + siz; if (hd == tl)
fread(hd = buf, , siz, stdin); return int(*hd++);
} inline int getI(void) {
register int ret = ;
register int neg = false;
register int bit = getC(); for (; bit < ; bit = getC())
if (bit == '-')neg ^= true; for (; bit > ; bit = getC())
ret = ret * + bit - ''; return neg ? -ret : ret;
} typedef long long lnt; const int inf = 1e9;
const int maxn = ;
const int maxm = ; int N, M, Q; int a[maxm];
int c[maxm]; int sum[maxn]; lnt ans[maxm]; struct edge {
int x, y, w, p; inline friend bool operator <
(const edge &a, const edge &b) {
return a.w < b.w;
}
}e[][maxm], d[maxm], b[maxm]; struct edit {
int x, y;
}q[maxm]; int fa[maxn]; int find(int u) {
return fa[u] == u ? u : fa[u] = find(fa[u]);
} inline void clear(int t) {
for (int i = ; i <= t; ++i)
fa[d[i].x] = d[i].x,
fa[d[i].y] = d[i].y;
} inline void merge(int x, int y) {
fa[y] = x;
} inline void contraction(int &t, lnt &cnt) {
clear(t); int tmp = ;
std::sort(d + , d + + t); for (int i = ; i <= t; ++i)
if (find(d[i].x) != find(d[i].y))
merge(find(d[i].x), find(d[i].y)), b[++tmp] = d[i]; for (int i = ; i <= tmp; ++i)
fa[b[i].x] = b[i].x,
fa[b[i].y] = b[i].y; for (int i = ; i <= tmp; ++i)
if (b[i].w != -inf && find(b[i].x) != find(b[i].y))
merge(find(b[i].x), find(b[i].y)), cnt += b[i].w; tmp = ; for (int i = ; i <= t; ++i)
if (find(d[i].x) != find(d[i].y)) {
b[++tmp] = d[i];
c[d[i].p] = tmp;
b[tmp].x = find(d[i].x);
b[tmp].y = find(d[i].y);
} for (int i = ; i <= tmp; ++i)d[i] = b[i]; t = tmp;
} inline void reduction(int &t) {
clear(t); int tmp = ;
std::sort(d + , d + + t); for (int i = ; i <= t; ++i)
if (find(d[i].x) != find(d[i].y)) {
merge(find(d[i].x), find(d[i].y));
b[++tmp] = d[i];
c[d[i].p] = tmp;
}
else if (d[i].w == inf) {
b[++tmp] = d[i];
c[d[i].p] = tmp;
} for (int i = ; i <= tmp; ++i)d[i] = b[i]; t = tmp;
} void solve(int l, int r, int now, lnt cnt) {
int t = sum[now]; if (l == r)a[q[l].x] = q[l].y; for (int i = ; i <= t; ++i)
e[now][i].w = a[e[now][i].p]; for (int i = ; i <= t; ++i)
d[i] = e[now][i], c[d[i].p] = i; if (l == r) {
ans[l] = cnt; clear(t);
std::sort(d + , d + + t);
for (int i = ; i <= t; ++i)
if (find(d[i].x) != find(d[i].y))
merge(find(d[i].x), find(d[i].y)), ans[l] += d[i].w;
return;
} for (int i = l; i <= r; ++i)
d[c[q[i].x]].w = -inf; contraction(t, cnt); for (int i = l; i <= r; ++i)
d[c[q[i].x]].w = inf; reduction(t); for (int i = ; i <= t; ++i)
e[now + ][i] = d[i]; sum[now + ] = t; int mid = (l + r) >> ; solve(l, mid, now + , cnt);
solve(mid + , r, now + , cnt);
} signed main(void) {
N = getI();
M = getI();
Q = getI(); for (int i = ; i <= M; ++i) {
e[][i].p = i;
e[][i].x = getI();
e[][i].y = getI();
e[][i].w = getI();
a[i] = e[][i].w;
} for (int i = ; i <= Q; ++i) {
q[i].x = getI();
q[i].y = getI();
} sum[] = M; solve(, Q, , ); for (int i = ; i <= Q; ++i)
printf("%lld\n", ans[i]);
}

@Author: YouSiki

BZOJ 2001: [Hnoi2010]City 城市建设的更多相关文章

  1. 【刷题】BZOJ 2001 [Hnoi2010]City 城市建设

    Description PS国是一个拥有诸多城市的大国,国王Louis为城市的交通建设可谓绞尽脑汁.Louis可以在某些城市之间修建道路,在不同的城市之间修建道路需要不同的花费.Louis希望建造最少 ...

  2. 2001: [Hnoi2010]City 城市建设 - BZOJ

    DescriptionPS国是一个拥有诸多城市的大国,国王Louis为城市的交通建设可谓绞尽脑汁.Louis可以在某些城市之间修建道路,在不同的城市之间修建道路需要不同的花费.Louis希望建造最少的 ...

  3. BZOJ2001 [Hnoi2010]City 城市建设 CDQ分治

    2001: [Hnoi2010]City 城市建设 Time Limit: 20 Sec  Memory Limit: 162 MB Description PS国是一个拥有诸多城市的大国,国王Lou ...

  4. 【BZOJ2001】 [Hnoi2010]City 城市建设

    BZOJ2001 [Hnoi2010]City 城市建设 Solution 我们考虑一下这个东西怎么求解? 思考无果...... 咦? 好像可以离线cdq,每一次判断一下如果这条边如果不选就直接删除, ...

  5. BZOJ2001: [Hnoi2010]City 城市建设

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2001 cdq分治+重建图. 可以保留当前一定会被选的非修改边然后把点缩起来.这样的话每次点数至 ...

  6. 【bzoj2001】 Hnoi2010—City 城市建设

    http://www.lydsy.com/JudgeOnline/problem.php?id=2001 (题目链接) 题意 给出一张无向图,$m$组操作,每次修改一条边的权值,对于每次操作输出修改之 ...

  7. [HNOI2010]CITY 城市建设

    问题: 给一张图,支持边长度修改,求MST 题解: 自己想就想不到了.. 考虑cdq分治 1.首先求出一定有用的边 对于未处理的边,全部设为-INF,求一次MST,出现在MST上的边一定最终出现在后面 ...

  8. BZOJ2001 [Hnoi2010]City 城市建设 【CDQ分治 + kruskal】

    题目链接 BZOJ2001 题解 CDQ分治神题... 难想难写.. 比较朴素的思想是对于每个询问都求一遍\(BST\),这样做显然会爆 考虑一下时间都浪费在了什么地方 我们每次求\(BST\)实际上 ...

  9. 【HNOI2010】城市建设(对时间分治 & Kruskal)

    Description \(n\) 个点 \(m\) 条边的带边权无向图.\(q\) 次操作,每次修改一条边的权值. 求每次修改后的最小生成树的边权和. Hint \(1\le n\le 2\time ...

随机推荐

  1. GJM :Unity集成Leap Motion

        Demo演示视频

  2. linux(十二)___Apache服务器用户认证、虚拟主机的配置

    创建xiangkejin  zhangsan两个用户 可看见文件中创建的两个用户: 建立虚拟目录并配置用户认证 ①建立虚拟目录 /xiangkejin ②在Apache的主配置文件httpd.conf ...

  3. 浅谈Angular的 $q, defer, promise

    浅谈Angular的 $q, defer, promise 时间 2016-01-13 00:28:00  博客园-原创精华区 原文  http://www.cnblogs.com/big-snow/ ...

  4. jQ图片列表光标移动动画

    本效果使用jQuery和CSS实现了图片列表,当鼠标移入时图片向左微动,移出则复原. 效果展示: http://hovertree.com/texiao/jquery/88/ 效果图如下: 其中的jQ ...

  5. Centos6.2设置静态ip和dns

    参考了如下文章:https://gist.github.com/fernandoaleman/2172388http://www.lifelinux.com/how-to-configure-stat ...

  6. 【搬砖】安卓入门(3)- Java开发编程基础--循环控制语句

    04.01_Java语言基础(循环结构概述和for语句的格式及其使用) A:循环结构的分类 for(初始化表达式;条件表达式;循环后的操作表达式) { 循环体; } 复制代码 B:循环结构for语句的 ...

  7. UICollectionView布局cell的三种方式

    UICollectionViewFlowLayout里面: // 方法一 - (void)prepareLayout{} // 方法二 - (nullable NSArray<__kindof ...

  8. Log4j记录日志步骤

    记录日志对调试Bug很有帮助  亲身体会 个人习惯用Log4J,大家可以在apache网站:jakarta.apache.org/log4j 可以免费下载到Log4j最新版本的软件包. Log4j支持 ...

  9. 初步进行vs单元测试

    首先提一下vs的安装过程,在官网下载免费社区版到本地,根据提示选择安装路径.以及大部分包文件开始安装,等待即可. eclipse的安装比vs多了JDK的下载安装,配置正确的path,以及在eclips ...

  10. nfs挂载配置

    nfs挂载步骤 服务器端 1.安装nfs-utils rpcbind $sudo yum –y install nfs-utils rpcbind 2.文件开放出去配置/etc/exports 例子: ...