题目链接:https://ac.nowcoder.com/acm/contest/375/C
这是第二次做到换根树dp了,第一次是在cf上,转移公式比较简单,当场做了出来。
大体题意:给一棵带编号无根树,问有多少种方式将这棵树删到仅剩一个节点。每次仅能删除叶子节点。
首先,可以确定这是一个树形dp。dp[x]表示最后删除x的方案数,我们把x当做根,就可以通过换根在O(n)内求出dp[1-n]。
大体思路确定后,开始进行第一步。假如已经确定树根,那么应该怎么求dp[root]。这个状态肯定要从dp[子树]转移过来,然后就不会做了,考虑到子树之间存在的相互影响,根本无从下手。
然后就到了该题的核心思想:我们把删除顺序改成给节点分配编号。假如要求dp[u],那么u肯定是最后一个删除的(dp数组的定义),所以u的编号肯定为siz[u]。子树v的对于u的贡献就是 C(剩余编号,siz[v]) * dp[v](想想为什么是dp[v]而不是size[v]!) 。
这样我们就解决了固定树根的问题,主要是把无从下手的删除节点,改为容易理解推算的编号分配。
接着就可以推算换根公式了,画画图算一下就出来了。
#include <bits/stdc++.h>
#define ll long long
#define mp make_pair
#define pb push_back
#define sec second
#define