题意

题目链接

给一个树的结点标序号,每次只能标相邻的点

问从每一个结点开始标,可行方案数

思路

对于一个结点 u 和他的子节点 vi

单考虑 vi 为根的子树,就相当于 [1, size(vi)] 的编号分配给这颗树的方案数

那么假设 vi 子树的方案数算好了, 更新 u 的时候, 要先分配给 vi size(vi)个编号

因为把分配给 vi 的编号离散化,就等价于 [1, size(vi)]

第一个子节点分配方案 C(size(u)-1, size(v1)), 第二个 C(size(u)-1-size(v1), size(v2)) 以此类推

-1 是 u 结点本身肯定是先编号的

然后就应该想到是换根DP了

换根之后(第二遍dfs)就感觉有点麻烦了

考虑原先父节点 u 对子节点 v 的影响

设这个影响值为 val, 就是 u 所有子节点的累计答案(就是第一遍下来的答案)去掉 v 的贡献再加上 u 父亲的贡献

之前计算 v 对 u 贡献时 C(size(u)-1, size(v1)), C(size(u)-1-size(v1), size(v2))…

因为是乘法,所以组合数可以提取出来,(因此搜索子节点的顺序不影响答案)

我们考虑去掉了子节点 v, 那么剩下的就是 size(u)-size(v) 给排列组合,相当于 C(size(u)-1-size(v1), size(v2)) 之后等等

所以我们去掉 v 贡献时, 去掉 C(size(u)-1, size(v))*dp[u][v] 即可

那么 u 父亲的贡献计算,u 父亲的大小就是 n-size(u)

先考虑 u 对 v 贡献,也就是 v 又分配给 u 结点 n-size(u) 个序号

同上,如果我们先考虑把序号分给 u 父亲,那么就不会对其他产生影响

代码

赛场上打的,有点乱