HDU 2586. How far away ?
链接
http://acm.hdu.edu.cn/showproblem.php?pid=2586
题意
多次询问,求树形图上两点间距离
思路一
重链剖分
将一个点与其拥有子树节点数目的节点相连,形成一条重链,一颗树最多有 $logn$ 条重链
当 $x$ 和 $y$ 不在一条重链上时,将所在链顶点深度大的那个点往上跳,直到在一条链上
时间复杂度:$O((n+m)logn)$
代码
1 |
|
思路二
树上倍增法
设 $f[x][k]$ 表示 $x$ 的 $2^k$ 辈祖先:$f[x][k]=f[f[x][k-1]][k-1]$
基于 $f$ 数组计算 $LCA(a,b)$ :
设 $d[b] \ge d[a]$
用二进制思想,把 $b$ 向上调整到与 $a$ 同一深度
若 $a=b$,$LCA=a$
用二进制思想,把 $a,b$ 向上调整,保持二者在同一深度且不相会
此时 $a,b$ 差一步就相会了,它们的父节点 $f[a][0]$ 就是 $LCA(a,b)$
时间复杂度为 $O((n+m)\log n)$
代码
1 |
|
思路三
Tarjan 算法
使用并查集“向上标记法”优化,这是一个离线算法
在 DFS 过程中:
将已经访问完毕并且回溯的节点标记为 $2$
将已经开始递归单尚未回溯的节点标记为 $1$
未访问过的节点没有标记
对于正在访问的 $x$,它到根节点的路径已经标记为 $1$
若 $y$ 是已经访问回溯的节点,则 $LCA(x,y)$ 就是 $y$ 向上走遇到的第一个标记为 $1$ 的节点
用并查集进行优化,将已经标记为 $2$ 的节点与它的父节点(标记必为 $1$ )合并
时间复杂度为 $O(n+m)$
代码
1 |
|