树
LCA
算法1:倍增 (预处理 $ nlog n $ )
code
算法2:欧拉序列上RMQ
算法3:Tarjan(离线,$ (n+q)a(n)$)
直径
树中两点间的最长路径
性质:
· 如果有多条直径,则所有直径之间都有公共点**
证明:如果两条直径没有公共点,可以利用这两条直径的四个端点中的两个构造除出一个更长的直径
· 直径的两个端点一定是叶子
· 树中距离某一直径端点最远的点,至少有一个是该直径的另一个端点
· 对于树上任意一个点,与之距离最远的每一个点,至少有一个直径的端点
证明:设与之距离最远的的点位x,任取一条直径(u,v),则根据3,易证(u,x)或(v,x)必定至少一个是直径
求直径:
1. 任取一个点,求距离这个点最远的点x,再求距离x最远的点y。根据性质4,我们知道这是一条直径
code
2.求LCA找直径。维护出每个点的最长链和次长链,更新直径即可
code
中心
该点到树中其他点的距离,最远距离最小
性质:
· 再某条直径上,并且到直径两端的距离差不超过1
· 即使树有多条直径,但树的中心至多两个,且均为直径中点
求中心:
预处理后,求出一条直径的两个端点x,y,直径长度R,以及x,y的最近公共祖先z
显然,如果x到z的距离小于R/2,那么该点在x到z的路径上
否则就在z到y的路径上
code
重心
若以某个节点为根时,它的每个子树大小都小于等于n/2,那么这个点就是重心(点分治会用到
性质:
·