树的直径
给定一个树,树中每条边有一个权值,树中两点间的距离定义为连接两点的路径边权之和。
树中距离最远的两个点间的距离被称为直径,连接这两个点的路径被称为最长链,也可以说是直径。
也就是说直径是一个数值概念,但同时也可指一条路径。直径可能不唯一。
我们一般认为这样一棵树是一棵带权无根树,即带权无向图。
求一棵树的直径
一般来说,树的直径有两种求法。
方法一:树形DP求树的直径
我们认为1号节点为树的根,那么这棵树就可以看作一棵有根树
设dep[ i ]为以i为节点的子树的最大深度,也可以理解为能够到达的最远的节点。
设它的子节点为son[ j ],那么dep[ i ] = max(son[ j ] + 边权)
然后,我们需要对每个节点i求出经过i点的最长链长度dp[ i ],那么整棵树的直径就很好求了,就是max(dp[ i ])
对于任意两个节点x,y,经过点i的最长链可以看成四个部分:从以x为根的子树中的最深点到x,从x到i,从i到y,从y到以y为根的子树中的最深点。
于是乎,dp[ i ] = max(dep[x] + dep[y] + 边权(x, i) + 边权(i, y))。
这样看起来有些复杂。
其实我们没有必要用两层循环来更新dp的值。在我们更新dep[ i ]的时候,当子节点枚举到x时,dep[ i ]中所保存的恰好就是从i到x加上从x到以x为根的子树中最深点,也就是dep[x] + 边(x, i)。
所以,我们可以先用dep