CodeForces 543D 树形DP Road Improvement

题意:

有一颗树,每条边是好边或者是坏边,对于一个节点为x,如果任意一个点到x的路径上的坏边不超过1条,那么这样的方案是合法的,求所有合法的方案数。

对于n个所有可能的x,输出n个答案。

分析:

题解

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <vector>
 6 using namespace std;
 7 
 8 const int maxn = 200000 + 10;
 9 const int MOD = 1000000007;
10 int n;
11 
12 vector<int> G[maxn], pre[maxn], suf[maxn];
13 
14 void scan(int& x)
15 {
16     x = 0;
17     char c = ' ';
18     while(c < '0' || c > '9') c = getchar();
19     while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
20 }
21 
22 int d[maxn], f[maxn];
23 
24 void mul(int& x, int y) { x = 1LL * x * y % MOD; }
25 
26 void dfs(int u)
27 {
28     d[u] = 1;
29     int sz = G[u].size();
30     for(int i = 0; i < sz; i++)
31     {
32         int v = G[u][i];
33         dfs(v);
34         mul(d[u], d[v] + 1);
35     }
36 
37     int p = 1, s = 1;
38     for(int i = 0; i < sz; i++)
39     {
40         mul(p, d[G[u][i]] + 1);
41         mul(s, d[G[u][sz-1-i]] + 1);
42         pre[u].push_back(p);
43         suf[u].push_back(s);
44     }
45 
46     reverse(suf[u].begin(), suf[u].end());
47 }
48 
49 void dfs2(int u)
50 {
51     int sz = G[u].size();
52     for(int i = 0; i < sz; i++)
53     {
54         int v = G[u][i];
55         f[v] = f[u];
56         if(i > 0) mul(f[v], pre[u][i - 1]);
57         if(i < sz - 1) mul(f[v], suf[u][i + 1]);
58         f[v]++;
59         if(f[v] >= MOD) f[v] -= MOD;
60         dfs2(v);
61     }
62 }
63 
64 int main()
65 {
66     scanf("%d", &n);
67     for(int x, i = 2; i <= n; i++)
68     {
69         scan(x);
70         G[x].push_back(i);
71     }
72 
73     dfs(1);
74     f[1] = 1;
75     dfs2(1);
76 
77     for(int i = 1; i <= n; i++) printf("%I64d ", 1LL * d[i] * f[i] % MOD);
78 
79     return 0;
80 }
代码君
原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4755263.html