CodeForces 543D 树形DP Road Improvement
题意:
有一颗树,每条边是好边或者是坏边,对于一个节点为x,如果任意一个点到x的路径上的坏边不超过1条,那么这样的方案是合法的,求所有合法的方案数。
对于n个所有可能的x,输出n个答案。
分析:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }