【每日一题】4月13日题目精讲 树型dp,换根
题号 NC51180
名称 Accumulation Degree
来源 《算法竞赛进阶指南》0x54
如果不会做的话可以先去学习另外一个题:201400 树学
写这两道题目中的任意题目,都可以获得牛币,写两篇题解可能获得更多牛币~
感谢@Alan233 同学推荐题目
如果你在题库做题时遇到了喜欢的题目,欢迎推荐给邓老师~ 点击查看详情
先看201400树学这个题
本题是要你任选一个点为根使得树上的所有点深度之和最小。
首先考虑如果是指定根节点你会不会做:已知根节点的话,我们只需要一遍dfs(或者bfs)就可以求出每个点的深度,然后求和就可以了。
然后我们考虑如果我们知道当前节点x为根的结果能否快速求出以它某儿子y为根的结果——当y从根的儿子变成根,它和它的子树都向上提了一层,深度-1,而x往下了一层,它除了y以外的其他子树也一起往下了一层,深度加以。所以从以x为根变为以y为根,深度之和减少了y的子树的大小,增加了其他点数的个数。
如果我们用f[i]表示以i为根的时候每个点深度的和,我们可以用一遍dfs把f[1]求出来——以1为根dfs,给每个点维护一个dep[i],显然(y是x的儿子),dfs结束之后求和就好。根据之前的分析在这次dfs的时候我们还需要同时维护一个数组cnt[i]表示i的子树大小(包括它自己),(y是x的儿子)。然后再来一次dfs,遍历到x点的时候,去计算x的每个儿子y的f值,。
最后只需要取f[i]的最小值就是答案。
这种解法实际上是利用了换根的思路,即先算出固定某一点为根的答案然后考虑把它的儿子换成根会发生什么样的变化,如果这个变化是比较好算的,那么我们就可考虑每个点x为根的答案都根据以它父亲为根的结果去推。
知道了这样子的思路我们再来看NC51180 Accumulation Degree。
首先,我们来看是不是能求出以某固定点(以1为例)的流量:
我们用flow[i]表示i点的流量:
(j是i的儿子)
这里特别要注意i点是叶子节点的情况,我们可以认为它的flow就是连向它的边流量就可以了。
接着,我们来考虑换根,flow[i]表示以i为根的流量——考虑当根从x变成x的儿子y的时候会发生什么?哪些量边哪些量不变? (想不清楚就画图,做算法题“草稿纸”还是很重要的。)
x的流量中没有从y过来的部分了 ,即此时x的流量其实是,但是此时的flow我们用它来表示以i为根的流量了(其实你也可以用另外一个数组存,但是并没有必要),所以并不更新flow[x]。
而x的流量会流向y,注意这里是x的新流量,而不是flow[x]。
特别注意叶子结点,当y是叶子节点的时候没关系,但是当x从根变为了叶子节点(说明x除了y这个儿子没有别的儿子了),它的流量并不是变成的上面的式子,而是直接变成edge[x] [y]。
看完邓老师的题解,记得自己去做题提高呀~
欢迎各位大佬来做题写题解,也欢迎大家踊跃在当日讨论贴中提问!
活动奖励:
在牛客博客中写出题解,并回复地址
审核通过可获得(依据题目难度和题解的内容而定)
本道题目4月20日中午12:00之前写的题解有获得牛币资格~
牛客博客开通方式
- 如何开通牛客博客:https://www.nowcoder.com/discuss/202952
- 如何使用博客搬家功能:进入博客--->设置--->底部博客搬家
- 如果你对牛客博客有任何意见或建议:牛客博客意见反馈专贴