[补档计划] 动态规划3 - 树形DP
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[补档计划] 动态规划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的主要内容,如果未能解决你的问题,请参考以下文章