HDU5647 Tree DP
这个题的意思是树的所有连通量的个数之和, 我们定义g[i]为以i为根的子数的个数, f[i]为以i为根的所有连通分量元素个数之和, 那么f[u] = f[u]*(g[v]+1) + f[v]*g[u]; g[u] = g[u]*(g[v]+1); 然后在回溯的时候计算一下即可, 代码如下:
#include <cstdio> #include <cstring> #include <vector> using namespace std; typedef long long LL; const LL m = 1e9+7; vector<int> G[200000 + 100]; int n; LL g[200000+100]; LL f[200000+100]; LL ans; void dfs(int u, int pre){ g[u]=1; f[u]=1; for(int i=0; i<G[u].size(); i++) { int v = G[u][i]; if(v != pre) { dfs(v, u); f[u] = (f[u]*(g[v]+1) + f[v]*g[u])%m; g[u] = g[u]*(g[v]+1)%m; } } ans = (ans + f[u])%m; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i=1; i<=200000; i++) G[i].clear(); int pi; for(int i=2; i<=n; i++) { scanf("%d", &pi); G[i].push_back(pi); G[pi].push_back(i); } ans = 0; memset(f, 0, sizeof(f)); dfs(1, -1); // LL res = 0; // for(int i=1; i<=200000; i++) res = (res + f[i])%m; printf("%lld\n", ans); // printf("%lld\n", res); } return 0; }