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
", ans);
//        printf("%lld
", res);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xingxing1024/p/5302540.html