树中第 K 远节点

有这样一个问题,给定一棵 N (2 ≤ N ≤ 150000)个节点的树,有 N - 1 条边,每边的长度为 L (1 ≤ L ≤ 1000000)对于每个节点 u,找出与 u 距离第 K 远的节点,输出这个距离。

有一个常规解法,列举出所有包含节点 u 的路径,遍历这些路径,找到第 K 远的节点,这也不是什么难事,n * n 复杂度。

列举包含所有路径的算法如下:枚举从一个叶子节点到另一个叶子节点的路径,若有 n 个叶子节点,则有 n * (n - 1)/2 条路径,设路径集合为 S,这些路径包含了这棵树中的所有路径(采用反证法,如果存在一条路径 p,没有被 S 包含,则向着叶子节点的方向,延长 p,直到 p 以叶子节点结束,得到新的路径 pp,它包含了 p,而 pp 一定被 S 包含,所以p 一定被 S 包含,所以假设不成立,故,树中任何一条路径一定被 S 包含)。

算法如下:

1.构建 HashMap<节点,距离)> nodeDistance;

2.那么以下标 i 遍历 S ,若i 在范围内,则对路径  si ,跳转到第 3 步;否则跳转到第 5 步;

3.若si 不包括 u 节点,跳过下面的处理,继续遍历。否则,转第 4 步;

4.遍历 si ,对于 si 中的每一个节点 nj ,距离 u 的路径为 dj ,将(nj,dj)作为一条键值对记录插入到 nodeDistance;跳到步骤 2;

5.对 nodeDistance 按距离排序,得到第 k 远的距离,并再遍历得到所有节点。

6.完成。

这个算法的复杂度为 n * n。而且上面只解决了一个确定的点的第 K 远距离,如果要解决所有节点的第 K 远距离,则复杂度为 n * n * n ,因为上一次的计算结果无法合理利用,再计算一个节点时,只能重新计算。

让我们再想一想,有没有更好的办法呢。我们想一下,u 的第 k 远的节点 t,与 u 的子节点有什么关系,或者当 t 不在 u 的子树中时,t 与 u 的父节点有什么关系?我们作图 1,表示一个节点的子树和非子树


图1 节点 u 的子树和非子树

图1中,h曲线内部的区域包含了 u 的子树,m 曲线内部区域包含了非 u 的子树。

我们观察图1,设 c(u,k) 表示所有( u 节点的子树中的节点,即区域 1 中的所有节点)离 u 第 k 远的距离,o(u,k) 表示所有(非 u 节点的子树中的节点,即区域 2 中的所有节点)离 u 第 k 远的距离。

则 u 节点的第 k 远的距离可以从集合:{c(u,1),c(u,2),c(u,3),...c(u,k)} U {o(u,1),o(u,2),o(u,3),...o(u,k)} 中取第 k 大的距离即可。我们令前一个集合为 C(u,k),后一个集合为 O(u,k)。令rank(k,A)是从集合 A 中求第 k 大的元素。

设最后所求为 F(u,k)。即 F(u,k) = rank(k,C(u,k) U O(u,k))

下面,我们先证明如下命题:

命题 1:与 u 第 k 远的节点必是从(区域 1 与区域 2 中的节点距 u 第 1 ~ k 远距离的节点)中选取。

证:假设节点 t 是区域 1 中距离 u 节点第 (k + 1) 远的节点,那么,节点 t 到 u 的距离必定在(区域 1 和区域 2 中所有节点离 u 的距离)中的排名大于 k + 1 ,所以 t 不可能是距离 u 第 k 远的节点,即,距离 u 第 k 远的节点,必定只能从区域 1 和区域 2 分别第 1 ~ k 远的节点中选取。即原命题得证。


下面,我们将关注点放在区域 1 距离 u 第 1 ~ k 远的距离(C(u,k))和区域 2 距离 u 第 1 ~ k 远的距离(O(u,k))求解上。

观察图 1 可知:

1.C(u,k) 必定是(所有 u 的直接子节点第 1 ~ k 远的距离集合)中的第 1 ~ k 远的元素组成的子集合。令 u1,u2,...表示 u 的直接子节点,有: 


C(u,k) = rank(k,C(u1,k) U C(u2,k) U ...)(式一)


2.O(u,k) 必定是((p 节点的所有直接子节点中除开 u 节点外,距离 u 第 1 ~ k 远的距离的集合) 与O(p,k)组成的集合中,第 1 ~ k 远距离的元素组成的子集合)。令 p1,p2,....表示 p 的直接子节点(除 u 节点外),有:


O(u,k) = rank(k,{C(p1,k) U C(p2,k) U ... } U O(p,k))(式二)


于是,这个问题可以这样解决:

1.对每个节点定义三个变量保存 C,O,F三个值

2.任选一个节点开始计算,通过 C 和 O 的计算(一个向子节点方向,也即向下遍历,一个向父节点方向,也即向上遍历),将所有节点都访问,于量,每个节点的 C,O 值都被计算,那么,每个节点的 F 值都被计算

3.算法结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值