本题要求统计:对于每一种长度d,有多少个subtree的最大直径等于d。根据长度来“构造”满足条件的树,其实是比较困难的。我们可以反过来想,对于每个subtree,我们查看它的最大直径是多少,然后做统计的aggregation。根据一个固定的subtree,求最大直径,这是一个确定性的问题,通常比构造性的问题简单的多。另外这个题目中节点数目小于等于15,穷举所有subtree(包括非法的不连通的图),也就是2^15=32768种,这是可以接受的。
给定了一棵树的拓扑结构,如何计算它的最长直径呢?这是一个经典的问题,有着经典的o(N)的解法:(参见 LC 1245.Tree-Diameter)
- 以图里的任意一个节点作为起始点A(看做根),往外做BFS遍历,能够到达的最远的节点B,那么B一定是最大直径的一个端点。
- 我们以B作为起始点(看做根),往外做BFS遍历,能够到达的最远的节点C,那么BC的路径就是最大直径的距离。
我们来给第一步的这个结论做个证明。第二步其实就是再次利用了这个结论。
假设从任意点A开始,能够到达的最远的距离是B。另外,整张图里“最长的点到点距离”是S和T。我们要证明B只可能是S或者T中的一点。如果不是,那么分情况讨论:
(1) AB与ST完全不相交。
A --X-- B
|
S --Y-- T
那么我们从A找一条能够到达ST的路径,并令分叉点是X和Y。因为AB是从A起始的最长路径,那么AB>AX+XY+XT,即BX>XY+YT.
那么我们观察路径S->Y->X->B,其距离SY+YX+XB > SY+2XY+YT = ST+2XY > ST
,这就与ST是全局“最长的点到点距离”矛盾。
(2) AB与ST相交于X。
A
|
S ==X== T
|
B
因为AB是从A起始的最长路径,那么AX+XB>AX+XS,即XB>XS.
我们观察路径B->X->T,其距离BX+XT > XS+XT = ST
,这就与ST是全局“最长的点到点距离”矛盾。
(3) 还有一些corner cases,都容易结合图形分析。
由此我们证明了,只要用两次BFS找到两个“最远距离”,就可以确定一棵树的最大直径。
本题的基本思路就是:
- 枚举节点的组合尝试构成一棵树
- 如果这棵树是联通的,那么就求它的最长直径。
- 对于该直径的subtree统计就加1。
如何快速判断树是联通的呢?很简单,在BFS的时候判断是否经过了所有这个树的节点就行了。