2021 ICPC区域赛(上海)H-Life is a Game(kruskal重构树、lca)

Problem - H - Codeforces

题目大意

  • 给你一个图,图上有点权和边权。以及q个查询:每个查询给你一个初始位置x和初始能量k;
  • 你每到一个新点上即可获得该点的能量(即点权),但是如果想通过一条边,你的能量总数需要大于边权(可以来回走)
  • 求可以获取的最大能量数。

首先很自然的想到由贪心的想到可能和最小生成树有关,可以联想prim算法的求解过程,但又不好单纯的用最小生成树写,这样每个点我都需要去跑一遍prim,就会超时。所以抽象一下题目就是我需要判断两个点x,y之间能不能走,首先可能需要跳到某个点z加上所有边权小于到z边权的所有点的能量,然后再看z能不能跳到这z,y之间的距离的最大值,而这又适合用kruskal重构树,所以又补了一下kruskal重构树.

kruskal重构树就是在排序所有点后做最小生成树时,每当两个点x,y要合并时,先找到x的祖先fx,y的祖先fy,新加一个点z作为fx,fy的父亲,同时新加两条边从z连向fx,fy,z的点权就是x->y的花费。这样做的好处是,可以使得任意两点间最小的距离经过的最大边权值为他们的lca,而且这样构造树是二叉的。并且如果边权如果是从小到大排序的话,这颗树是大顶堆的。

总结下来就是

了解完kruskal重构树后我们再来想找个问题,这个时候构成的树叶子节点全部都是图中原来有的点, 然后我们对于一次查询就是对于一个叶子节点来说,每走到一个点就是获得以这个点为根的子树上的所有节点和,所以对于这个叶子节点来说我只需要尽量爬到根节点就行,因为爬到根节点我就已经可以获得它下面的所有能量了,那么怎么个爬法呢?直接暴力爬感觉还是不能解决问题,依然可以构造一个为链的树卡成o(n).

想到往上爬,又得是log的复杂度,我们可以试试往lca方向想一想。

首先我们可以知道如果我爬不到父节点,那必不可能爬到父节点的父节点,如果我可以到父节点,那从父节点到祖父节点一定是会更容易的,所以这个时候就可以递归判断,首先先判断到父节点的距离,然后到祖父节点的距离就是min(mx[x][i-1],mx[fa[x][i-1]][i-1]),mx是指从哪个点跳到2^i的父亲所需要的最小初值为多少,中间用了倍增的搞法搞一下,然后就得到了每个点到每个在它上面的点的最小距离。预处理这些距离后,就可以在每个查询里,倍增的跳,因为是二进制的跳,所以它一定可以跳到它最大可以到的位置,保证了log的复杂度,这道题就结束了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值