4052 树
2023-08-09 20:33:34 # OI # Problem

题面

内容

有一棵 nn 个点的树,求有多少序列 a1<a2<<ak(k2)a_1 < a_2 < \cdots < a_k(k \ge 2),且树上从 a1a_1aka_k 的路径依次经过 a1,a2,,aka_1, a_2, \cdots, a_k

答案对 109+710^9 + 7 取模。

输入

输入第一行一个整数 nn

接下来 n1n - 1 行,每行两个整数 u,vu, v,表示树上的一条边。

输出

输出一行一个整数,表示可能序列的个数模 109+710^9 + 7 的结果。

样例1

输入

5
5 3
5 4
3 1
1 2

输出

14

提示

对于所有数据,满足 2n50002 \le n \le 5000

样例 1 解释:
合法序列为:(1,2),(1,3),(1,4),(1,5),(2,3),(2,4),(2,5),(3,4),(3,5),(4,5),(1,3,4),(1,3,5),(2,3,4),(2,3,5)(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5), (1, 3, 4), (1, 3, 5), (2, 3, 4), (2, 3, 5):这些序列在树上从最小值走到最大值从小到大依次经过了序列中的点。

思路

定义fif_i是从以ii为根的子树中选出单调递减的路径的方案数,gig_i是从以ii为根的子树中选出单调递增的路径的方案数。

对于每个节点一开始f,gf,g值都为11,因为它们还没有假如任何其它节点,只能选自己的方案数为11。然后开始dfsdfs,在回溯的时候处理fi+=i>kfk,gi+=i<kgkf_i+=\sum_{i>k}f_k,g_i+=\sum_{i<k}g_kkkii的子树内。

image.png

image.png

递归的时候选取一个点作为要选的两个点的 LCA ,然后选取离这个点最近的两个点设为x,yx,y,那么我们就需要首先合并xxlcalca,也就是更新lcalca的信息(f,gf,g),然后合并完之后这就是一个新的集合,那么就可以把它和以yy为根的子树进行合并,合并的时候分别枚举两个集合中的点i,ji,j,假如i<ji<j,那么答案累加就是ans+=fx×gyans+=f_x\times{g_y},因为是iji\to{j}的一条路径,所以iixx是单调递减的。相反地,如果i>ji>j,那么就是ans+=fy×gxans+=f_y\times{g_x}

先合并 lca 和它的第一个子树,也就是目前知道11子树的信息以及根节点00当前的信息,很显然11没有其它子树,它的信息不会再被更新,而00还是有其它子树的,也就是说它的f,gf,g仅限于当前遍历到的子树,即11

那么我们再枚举其它子树,实际上就是不断合并连通块更新信息的同时并累加答案。

这样全部合并完后,ansans就是答案。