树分治总结

一.前言

树分治就是在树形结构上进行分而治之的操作,包括点分治和边分治。

①点分治的效率比较稳定,最坏情况下递归深度为O(logn)。

②边分治在定点度数D为常数时,基于边的分治递归最坏深度为O(log N) ,然而D较大时会达到O(N),这种效率显然是不行的,不过可以通过添加虚点,使得每个节点的度数都不大于3,这样既可保证效率。


二.点分治

例题:POJ-1741

题意:一棵有n个节点的树,每条边有个权值代表相邻2个点的距离,要求求出所有距离不超过k的点对(u,v)

点分治算法的过程:

1)找出树的重心

①计算以u为根的树中每棵子树的大小

②根据子树大小找出树的重心root(以树的重心为根的树,可以使其根的子树中节点最多的子树的节点最少)

2)将树的重心作为根节点root,计算树中每个点到root的距离dir

3)计算树中所有满足dir[u]+dir[v]<=k的点对数cnt1

4)计算以root的子节点为根的子树中,满足dir[u]+dir[v]<=k的点对数cnt2

5)ans+=cnt1-cnt2

6)删掉节点root,分别遍历root的子树,回到第1)步

题解链接:POJ-1741


三.边分治

边分治的主要过程:

首先为了保证效率(边分治递归深度是由点的度数决定的),要添加虚点用来“平衡”节点的度数,重建树的算法以后再补上。

边分治就是选在当前分治结构里面选一条边,使得边的两端最大子树尽可能的小,这样的边我们称作中心边不同于点分治的是,中心边只会把树分成2个子树,因此处理起来比较方便,找中心边的方法和找重心的方法一样,都是要找使最大子树尽可能小的那一条边。

对于一个分治结构,假设找到的中心边为x-y,对于这个分治结构中的路径只有两种:不经过边x-y的和经过边x-y的,前者由子分治结构来考虑,现在只考虑后者。处理完当前子树后,删掉中心边,将子树分成2个联通块,再进行递归操作。


例题:SPOJ-QTREE4

题意:

给定一棵树,节点有黑白两种颜色,有正负的边权。有两种操作:

①修改反转某个节点的颜色;

②询问树上最远的两个白色节点的距离。


边分治算法的过程:

1)添加虚点,使每个点的度数不超过3,虚点的颜色定为黑色(不对查询有影响)

2)每层选中一条中心边(找中心边方法同找重心方法)

3)删掉中心边,可以分成左右两个子树

4)左右子树各维护一个单调队列,分别记录白点到子树根的距离

5)对于每个白点,记录自己在哪几个队列中(修改时要用)

6)ans=max{左子树的ans,右子树的ans,左子树的最远距离+右子树的最远距离+中心边长度}

7)递归遍历左右子树,回到第2)步

8)修改操作:

①白色->黑色:把包含u的所有根节点的队列进行更新(弹出黑色节点),并更新ans

②黑色->白色,将u放入包含u的根节点的队列中,并更新ans

题解链接:SPOJ-QTREE4

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前序遍历是二叉遍历的一种方式,在分治策略中,前序遍历按照根节点、左子、右子的顺序进行遍历。以下是分治策略题目前序遍历的步骤: 1. 首先,将根节点压入栈中。 2. 循环执行以下步骤直到栈为空: a. 弹出栈顶节点,并将其值添加到结果列表中。 b. 如果栈顶节点的右子存在,则将右子压入栈中。 c. 如果栈顶节点的左子存在,则将左子压入栈中。 这个解法是非递归的通用解法,按照前序遍历的规则来处理节点。通过维护一个栈,将需要遍历的节点按照先右后左的顺序压入栈中,然后依次弹出栈顶节点,将其值加入结果列表,并将右子和左子压入栈中,重复这个过程直到栈为空。 此外,前序遍历还可以使用递归算法来实现。递归算法的思路是先处理根节点,然后递归地处理左子和右子。在分治策略中,递归算法可以将大问题分解成小问题,先处理根节点,然后递归地处理左子和右子总结起来,分治策略题目的前序遍历可以通过非递归通用解法或递归算法来实现。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【C语言】数据结构-链式二叉,详解分治递归和层序遍历](https://blog.csdn.net/muxuen/article/details/124212851)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [14 二叉的前序遍历(Binary Tree Preorder Traversal)](https://blog.csdn.net/SeeDoubleU/article/details/119834420)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值