树的直径和重心

重中之重(别忘了我(蒟蒻)名字的翻译)

最基础的树的直径和重心

我是分割线---------------------------------------------------------------------------------------------------------

树的直径

我是分割线---------------------------------------------------------------------------------------------------------

树的直径(Diameter)是指树上的最长简单路没错不是它有多宽(e.g.)
直径的求法:两遍搜索 (BFS or DFS)。
过程:任选一点w为起点,对树进行搜索,找出离w最远的点u。以u为起点,再进行搜索,找出离u最远的点v。则u到v的路径长度即为树的直径。

简单证明:

如果w在直径上,那么u一定是直径的一个端点。反证:若u不是端点,则从直径一端点到w再到u的距离比直径更长,与假设矛盾。

如果w不在直径上,且w到其距最远点u的路径与直径一定有一交点c,那么由上一个证明可知,u是直径的一个端点。

我是分割线---------------------------------------------------------------------------------------------------------
上方证明的过程

如果w到最远点u的路径与直径没有交点,设直径的两端为S与T。

wu为w引出的最长路:

wu>wc+ct

st为直径(即st应最长)But:

sc+cw+wu>sc+cw+wc+ct

而:

sc+ct=st(最长路??)

so su比直径还长吗?

so u一定在直径上。

因此w到最远点u的路径与直径必有交点。

 S-----------c-----------T

             |

             |

            w------u
我是分割线---------------------------------------------------------------------------------------------------------

简单水 题

示例代码

我是分割线---------------------------------------------------------------------------------------------------------

树的重心

树的直径和重心_第1张图片

算法流程

首先,利用前向星存边建立边表。由于无向,所以要连两次边。我们用一次 dfs() 建立以1为根节点时每个结点所在子树的结点数。

接下来考虑把这个点删掉的结果,如果一个非根结点有 p 个儿子,那么删掉这个点之后会有 p+1 个连通分量,因为这个结点不是根节点,那么除了这个结点及它的所有子树外还有一个连通分量,我们将之称为这个结点的上方子树。接下来,计算这些子树(包括上方子树)的 size (指以当前节点为父亲或祖宗的节点数总和)再从中找个最大值,因为总共有 n 个结点所以有 n 个最大值,接下来在其中挑一个最小的即可,当这个值取到最小时的那个结点就是这棵树的重心。

size 的计算方法:

结点 u 的子树,直接利用 size 即可。

结点 u 的上方子树,可以利用求补集的思想,总共有 n 个结点,这个结点及其所有子树的结点和为 size(u), 那么它的上方子树的 size 就是 n−size(u) 。
附图一张(看不懂看图自):
树的直径和重心_第2张图片

代码

树的直径和重心_第3张图片

重心进阶(自带例题和代码)

你可能感兴趣的:(树的直径和重心)