HDU 6393 2018HDU多校赛 第七场 Traffic Network in Numazu(树链剖分 + 树状数组)

 

大致题意:给你一个含有一个环的树,即n个点n条边的图,然后动态修改每一条边的边权,同时动态询问任意两点之间的最短距离。

非常裸的一道图论+数据结构题。首先,我们考虑如果没有环的情况下,那就是一个显然的树链剖分+线段树/树状数组的题目,但是现在有一个环就变得不一样了。但是这种题目显然是要把树变成环的,于是我选择环上的一条边剪断,选择环上任意一个点为根,这样就可以构成一棵树了。

具体来说,我把树分为两个部分,一个是环上的点,一个是非环上的点。对于环上的点,我们维护一个树状数组0,表示环内各个点不绕圈的情况下相互到达的距离。对于非环上的点,我们维护一个树状数组1,表示所有非环上的点距离其最近的一个环上的点的距离。这样,对于任意一个查询(x,y),首先判断距离两个点最近的环上点是否是同一个点,如果是的话,说明两个点之间的最短路并没有经过一条环上的边,因此我们直接用树状数组1内,x、y以及其lca对其最近的环上点的距离,求和作差即可。对于两个点最近的环上点不是同一个点的话,那么我们要把最短路分为三个部分,第一是x与其最近的环上点的距离,第二是y与其最近的环上点的距离,第三是两个环上点之间的距离。具体来说可以见下图。

                                   

其中黑色的点表示环上的点,那么相当于把黑色的点当作整个树的主心骨,然后对于非环上的点,树状数组就保存其距离最近的黑色的点的距离。然后黑色的点之间的距离是 树状数组中两点的距离 和 转一圈之后二者的距离 的最小值。

具体做法的话,首先找到环上的点并标记,然后从每一个环上的点开始往外拓展非环上的点,并把每一个拓展出来的点的id标记为对应开始拓展点的编号。拓展的同时,维护树状数组。之后,再拓展环上的点,对每一个环上的点重标号,记录为hid,维护树状数组。然后查询和修改的时候按照之前所说的修改即可。具体见代码:

#include<bits/stdc++.h>
#define LL long long
#define clr(x,n) mems
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值