随笔分类 - 动态规划 - 树形dp
摘要:首先,肯定没有不合法情况(每条边的权值都赋值为 $1$ 就一定合法) 然后对于一条边 $(x,y)$ 来说,只可能有 3 种取值. 1. 取 $a[x]$ 2. 取 $a[y]$ 3. 取 $m$ 然后转化成这一步后就可以进行树形 DP 了. 令 $f[x][0],f[x][1]$ 分别表示以 $x
阅读全文
摘要:神仙容斥+DP可还行. code: #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #define N 1007 #define ll long long #de
阅读全文
摘要:本来以为这道题会非常难调,但是没想到调了不到 5 分钟就 A 了. 由于基于多项式的运算都可以方便地进行封装,所以细节就不是很多(或者说几乎没有细节) 题意:给定一棵树,每个点有点权,求对于所有大小为 $m$ 的独立集的点权之积的和. 数据范围:$n,m \leqslant 8 \times 10^
阅读全文
摘要:现在看来这道题就简单了. 首先要知道,树形 DP 的复杂度是 $O(n^2)$ 的(通过严格控制子树大小,均摊下来一个状态只会贡献 n 次). 然后这道题要求选的个数最多为 $k$,所以复杂度就是 $O(nk)$ 的. 设 4 个状态:$f[x][y][0/1],g[x][y][0/1]$ 分别代表
阅读全文
摘要:比较好的一道虚树题. 建出虚树,然后计算虚树中距离点 $x$ 最近的关键点,这个来一次树形dp+换根即可实现. 难点在于计算 $x$ 到 $x$ 父亲这一段所有节点归属于谁(肯定属于 $x$ 的最近点或 $x$ 父亲最近点). 这里的话肯定可以二分出拐点(拐点以前属于 $x$,拐点以后属于 $y$)
阅读全文
摘要:由于有重复数字,所以这个问题就很不好处理. 考虑我们让 $i$ 为根,这个点对答案的贡献就是以 $i$ 为根,由 $val[i] \leqslant val[j]$ 的 $K$ 个点组成的连通块个数. 但是我们会发现如果直接求的话会算重一部分. 如果 $val[j]>val[i]$ 的话,将这个点设
阅读全文
摘要:对于树边直接转移,然后按照套路拆环,在环上做一个单调队列 DP. 一种方案虽然在一个换上可能算不了,但是一定可以在另一个环上计算到. 仙人掌上 DP 的套路就是遇到树边就按照树上做,遇到环就拆环,做一个环形 DP. code: #include <bits/stdc++.h> #define N 2
阅读全文
摘要:对于树的情况是简单的. 我们 DFS 这颗仙人掌,对于树边正常转移就行. 然后对于环,我们把环拿出来,然后强制讨论端点选/不选再跑一遍 DP 就行. code: #include <bits/stdc++.h> #define N 200006 #define setIO(s) freopen(s"
阅读全文
摘要:开始的时候没有借助圆方树去思考,思路非常混乱,想了很长时间后冷静下来发现这题不就是分类讨论简单题嘛... 题目不难,分两种情况讨论: 设当前点为中间点(圆点) 起点从一个儿子的子树进入到中间点后进入到另一个儿子的子树. 起点从一个儿子的子树进入到中间点后仍然回到该儿子子树中(相当于上一条的子问题)
阅读全文
摘要:这道题和网络收费那道题的套路是一样的. 都是直接枚举每一个点的状态. 但是要注意:这里枚举每个点的状态是基于 dfs 的,所以有递归式:$f(T)=4\times f(\frac{T}{2})$ (算两次) 那么就有 $f(ROOT)=4^n$. 这个是仅考虑 dfs 部分的复杂度,要是把背包部分算
阅读全文
摘要:朴素的高斯消元是 $O(n^3)$ 的,但是由于叶节点是终止节点,所以可以逐层向上推成 $k\times f(fa)+b$ 的形式. 推到根节点时直接取根节点的 $b$ 值就可以了. code: #include <cstdio> #include <cstring> #include <algor
阅读全文
摘要:令 $f[x][j]$ 表示以 $x$ 为根的子树,选出连通块的异或值为 $j$ 的方案数. 然后有 $f[x][j]=f[x][j]+\sum_{i\oplus k=j} f[x][i] \times f[son][k]$. 其中,$\oplus$ 为异或符号. 求解这个东西显然可以用 $FWT$
阅读全文
摘要:我们令 $f[i]$ 表示以 $i$ 为根的删除方案数. 这里一定要注意一件事情:根据我们的定义,我们已经默认 $i$ 点为根的子树在删除时 $i$ 是最后删除的. 然后按照换根 DP 的套路转移就行,但是转移的时候组合数一定要注意. #include <cstring> #include <cst
阅读全文
摘要:题意: 给定一张图,和这个图的一颗生成树. 求:重新对这颗树标号,有多少种标号方式满足如果一条边 $(x,y)$ 在树中出现的话在图中也出现. 暴力做法:$f[i][j][S]$ 即在以 1 为根的树中遍历到点 $i$,该点映射的点是 $j$,且 $i$ 这颗子树映射的点集是 $S$. 转移的话时间
阅读全文
摘要:code: #include <cstdio> #include <cstring> #include <algorithm> #define ls x<<1 #define rs x<<1|1 #define N 2105 #define ll long long #define setIO(s)
阅读全文
摘要:换根DP 求一下每个点为起点的最长路径,然后用双指针扫一下统计答案就好了. code: #include <cstdio> #include <queue> #include <set> #include <algorithm> #define N 1000007 #define ll long l
阅读全文
摘要:状态还比较自然. 令 $f[x][j]$ 表示 $x$ 的子树全被控制,且多出来 $j$ 层. 令 $g[x][j]$ 表示还需要 $j$ 层才能控制 $x$ 所有子树. 转移 $f[x][j]$ 的时候有两种情况:之前已经控制:$f[x][j]+g[y][j]$,之前没控制:$g[x][j+1]+
阅读全文
摘要:显然01分数规划转成二分答案+判断是否大于 0 的问题. 这个题有一个坑点:不止根节点的父亲可能是 0 号节点(0号节点也是不能省略的) code: #include <cstdio> #include <string> #include <cstring> #include <iostream>
阅读全文
摘要:这个题有一个结论:如果用 $x$ 个点能凑出的给点个数在 $[L,R]$ 之间,那么任意 $v\in [L,R]$ 一定能取到. 知道这个结论之后跑一个树形背包就行了,注意在跑背包的时候上界一定要限制好,要不然时间复杂度会多一个 $O(n)$ 的. code: #include <cstdio> #
阅读全文
摘要:倒在了性质分析上....(还有仔细读题) 仔细读题后,我们发现红色边只能连接一个连通块和一个叶节点(或两个叶节点). 然后如果一个状态是合法的,当且仅当以某个点为根时所有蓝边都是形如 son[x]->x->fa[x] 然后因为有这条性质,我们就可以进行树形DP了. 令 $1$ 为根,$f[x]$ 表
阅读全文

浙公网安备 33010602011771号