首页 > 代码库 > [补档计划] 动态规划3 - 树形DP
[补档计划] 动态规划3 - 树形DP
树形DP 是一类 OI 中的问题, 即对一棵树进行 DP .
很多时候要进行两次 DP , 第一次处理子树内的情况, 第二次处理所有的情况.
关键靠做题.
[CF697D] Puzzles
题意
给定一棵 $N$ 个节点的树.
求进行 DFS , 每个节点的时间戳的期望值.
分析 树的遍历 & 特性分析
进行 DFS , 根的时间戳一定是 1 .
$f[1] = 1$ .
$f[next] = f[x] + \sum_{i = 1} ^ c \frac{1}{c} \sum_{son \ne next} size[son] + 1 = f[x] + \frac{1}{2}\sum_{son\ne next}size[son] + 1$ .
实现
#include <cstdio> #include <cstring> #include <cstdlib> #include <cctype> #define F(i, a, b) for (register int i = (a); i <= (b); i++) #define fore(k, x) for (register int k = hd[x]; k > 0; k = nx[k]) #define db double const int N = 100005; int n, tot, hd[N], nx[N], v[N]; int s[N]; db f[N]; inline int rd(void) { int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; int x = 0; for (; isdigit(c); c = getchar()) x = x * 10 + c - ‘0‘; return x * f; } inline void Ins(int x, int y) { nx[++tot] = hd[x], hd[x] = tot, v[tot] = y; } void Siz(int x) { s[x] = 1; fore(k, x) { Siz(v[k]); s[x] += s[v[k]]; } } void Solve(int x) { long long sum = 0; fore(k, x) sum += s[v[k]]; fore(k, x) { f[v[k]] = f[x] + 1 + (sum - s[v[k]]) / 2.0; Solve(v[k]); } } int main(void) { #ifndef ONLINE_JUDGE freopen("CF697D.in", "r", stdin); freopen("CF697D.out", "w", stdout); #endif n = rd(); F(i, 2, n) Ins(rd(), i); Siz(1); f[1] = 1.0; Solve(1); F(i, 1, n) printf("%0.8lf ", f[i]); printf("\n"); return 0; }
[补档计划] 动态规划3 - 树形DP
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。