| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 树上操作(边分治) -> 正文阅读 |
|
[数据结构与算法]树上操作(边分治) |
今天我们浅谈一下树上操作的边分治,首先我们要了解一下为什么要使用边分治,当我们处理问题的规模很大时,用暴力的方法O(n^2)会导致时间超时,而使用边分治,点分治每次会将树分为将近n/2的子树,所以点分治,边分治会将时间复杂降为O(nlogn)。 边分治是指在给定的一个树中,找到一条边(中心边),将这条边删去,使得删去这条边后分成的两个子树的大小尽可能相等。边分治和点分治所解决的问题基本上是相同的,但是基于边的分治只需要考虑两棵子树,所以设计算法更为简单。找中心边的方法和找重心的方法一样,找使最大子树尽可能小的那一条边。 假设中心边为x-y,则树中任意两个点的路径可以分为两种:经过x-y,不经过x-y。 不经过x-y的路径在以x,y为根的两个子树中,可以递归求解。 需要注意的一点是,边分治对菊花图的处理,如图: 在处理这种图的时候发现,所有路径都经过中心边,算法的时间复杂会退化为O(n^2),此时需要将树转化一下,转化树有两种方法: 第一种方法是从1开始枚举每个点,对于一个点x,如果他有<=2个子节点,那么直接向子节点连边即可;否则新建两个点,将x连向这两个点,并将x的子节点按奇偶分类暂时归为这两个新建点的子节点。为了不影响原树深度等信息,我们将连向新建点的边权设为0。这样新建树因为每条原树边会被存logn次,所以空间复杂度是O(nlogn)。
第二种方法是dfs整棵树,对于原树每个点x,记录一个last(初始为x),每次将lastlast连向一个子节点,并新建一个点y将lastlast连向y,然后将last改为y。同样将连向新建点的边权设为0。因为每个原树边只被保存一次,所以空间复杂度是O(n)。需要注意的是这里和线段树一样要开四倍空间。
将图重建完毕之后就是找中心边 求中心边的方法与点分治中求中心的方法类似,只需进行一次深度优先遍历,使删除该边后的最大子树最小,代码如下:
接下来就是中心边分解,方法是: (1)找出中心边midedge,得到中心边的两个端点p1,p2,然后删除p1的邻接边midedge,删除p2的邻接边midedge; (2)分别从p1、p2出发递归求解 (3)更新树根rt的ans;
关于边分治的例题 (2)树上查询Ⅱ(SPOJ QTREE5) (3)树上两点之间的路径数(POJ1741) |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 5:50:07- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |