树形动态规划
错题
P8867 [NOIP2022] 建造军营
易分析出tarjan+树形DP
正如题解所说,有两种取消后效性的方法:加维或换定义
加维好想,但是比较难写,不过我倾向于加维,思路清晰不易错
p.s. 一定一定,要保证方程无后效性
md,拿了个有后效性的方程搞了2个小时
P4099 [HEOI2013]SAO
超级好的一道题,对于我这种DP蒟蒻来说
首先,这道题不能脱离树而去做DAG(自己研究了也会发现)
易想到DP方程\(f[x][j]\)为点\(x\)在子树\(x\)内排在第\(j\)为的方案数
难点在于转移:由于定义为子树内,考虑对儿子\(v\)的排序往\(x\)上合并
注意考虑有向边的限制,列出DP方程为:
比较考验推导能力,建议试试,时间复杂度为\(O(n^3)\)
然后就是观察到\(f[v][l]\)可以前缀和预处理,优化掉了一个\(O(n)\),总时间复杂度为\(O(n^2)\)
时间复杂度分析
重头戏来了
乍一看这个式子,每个点搜过一遍,对于每个点\(v\)的穷举次数为\(siz[x]*(siz[x]+siz[v])\),乍一看感觉像\(O(n^3)\),再想想又不到,感觉有个常数级别的差距或可能为\(O(n^2logn)\),结果是\(O(n^2)\)
仔细思考这个过程:每次枚举\(siz[x]*(siz[x]+siz[v])\),对于\(siz[x]*siz[v]\)来说,相当于枚举整棵树的所有点对,故为\(O(n^2)\)……
树的直径
方法1:两次DFS
方法2:树形DP
我们不改变树的形态(即根不变),发现此时直径上总会有一个点深度最小,即它和它的全部子树包含直径的全部点集,因此我们做出以每个点为根的最长链,一定有一个点包含正确答案。
设f[i]表示以i为根的最长链长度
设g[i]表示以i为根的次长链长度,且该次长链不与最长链有交集
DFS枚举子树后转移即可
p.s.转移时注意跟次长链比较
p.s.s.这种记录次优值的思路在单源次短路中也有体现
树的重心
换根
最大权独立集
基环树DP
剖环成树,然后做树形DP即可
找环
拓扑排序
易知一遍拓扑后只剩下环,记录即可
注意基环树存储时用的是无向图,因此进队条件改为in[v]==1
边界处理
正常来说,走环的时候要往一个方向,因此只要让它不回头就不会重复走,于是很容易想到pre记录上一个走到的点
然而这是错误的!
考虑二元环,我下一个走的点就是我上一个走到的点,所以到不了另一个(这\(\beta\)二元环整了我一下午+一晚上)
于是考虑记录上一步走的边
但是这是无向图呀,我连了双边,记不到回去的边啊
考虑网络流算法时建反图,让tot从2开始计数,就是为了可以用i^1来快速跳转到自己的反边
于是我们利用这个技巧,问题解决
p.s.断点本身就是异类,基环树DP大致思路都是断边成树,然后整棵树做DP,像这道题我的做法就会引发一系列细节问题,但正常思路就不会(说不定某一题用我的方法更好呢)
P6830 [IOI2020] 连接擎天树
首先发现存在\(p[i][j]=3\)是非法的,因此图为基环树森林
先把树连出来,再拼环即可
换根DP
两次DFS
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号