树的问题经常考,建议 \(CSP\) 前学会求直径(两种方法),重心,LCA(建议学会倍增和树剖,用途广泛)
经常要用到的东西:树的直径,重心,求LCA。
树的直径
与直径相关的结论1:与一个点距离最大的点为任意一条直径的两个端点之一。
与直径相关的结论2:两棵树之间连一条边,新树直径的两个端点一定为第一棵树直径的两个端点和第二棵树直径的两个端点这四者中之二。
求直径:
1.\(O(n)\) 的 \(dfs\) 两次,注意边权不能是负数
2.\(O(n)\) 的 \(DP\) ,边权可以是负数
3.动态求直径
树的重心
\(1.\) 把重心删去后剩下的子树 \(size\) 不超过原树的 \(\frac{1}{2}\)
\(2.\) 把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上。
\(3.\) 一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。
\(4.\) 一棵树最多有两个重心,且相邻。
求重心:
\(O(n)\) 求 \(size\) 后取 \(mx\) 最小的,点分治基本操作。
LCA
树上两点距离:\(dep[x]+dep[y]-2 \times dep[lca]\)
求LCA:
倍增:O(log),还可以用来求 \(k\) 级祖先。
树剖: O(log),跑得快,可以套上线段树
离线Tarjan:没写过
st表: O(1),用来卡常,但不一定跑的比树剖快,只是理论优秀罢了...