首页 > 其他分享 >简单树上问题

简单树上问题

时间:2024-02-08 20:11:36浏览次数:14  
标签:结点 子树 最大值 大值 DFS 问题 简单 树上 dp

1. 树的重心

树的重心是无根树上的一个应用。满足以下性质的点 \(u\) 为树的重心:

删除结点 \(u\) 即与它相连的边,如果在剩下的两棵或多课子树中最大子树的结点数最少,那么 \(u\) 就是树的重心。

例1 POJ-3107 翻译

本题的教父就是树的重心。接下来分析方法。

首先是暴力法。枚举一个点,设它为重心,计算出删除它后剩下的子树中最大子树的结点数来判断是否合法。计算节点数时可以用 DFS。这样时间复杂度为 \(\mathcal{O}(N^2)\),不能通过本题。

只需要做一次 DFS 就可以求解。

设结点 \(1\) 为根。用 \(S_i\) 表示结点 \(i\) 的子树的结点数,这样 \(S\) 可以用一次 DFS 求出。那么去掉结点 \(u\) 后,\(u\) 的所有子节点会成为单独的树,它们的大小在 DFS 的过程中已经求出;\(u\) 的父节点也会成为一棵单独的树,它的大小即为 \(n-S_u\)。这样就可以在一次 DFS 的同时求出树的重心了。

代码

2. 树的直径

树的直径是指树上最远的两点之间的距离。有两种方法求树的直径:

  1. 两次 DFS 或 BFS。

  2. 树形 DP。

这两种方法的时间复杂度都为 \(\mathcal{O}(N)\)。

方法 \(1\) 可以记录路径,但不能处理负边权。

方法 \(2\) 可以处理负边权,但不能记录路径。

  1. 两次 DFS 或 BFS

例1 洛谷-U283565

DFS 或 BFS 可以处理没有负边的树。方法很简单:

  • 在树上找任意一点为起点,用 DFS 求出到这个点距离最远的点 \(s\)。

  • 接下来以 \(s\) 为起点,用 DFS 求出到 \(s\) 最远的点 \(t\)。

  • \(s,t\) 即为树的直径的两个端点。

代码

  1. 树形 DP

设 \(dp_u\) 表示 \(u\) 的子树中距离 \(u\) 最远的点的距离。那么状态转移方程如下:

\(dp_u=\max(dp_v+w)\),其中 \(v\) 是与 \(u\) 相连的点,\(w\) 是 \(u\) 到 \(v\) 边的权值。

再用 \(f_u\) 表示经过点 \(u\) 的最长路径长度。那么状态转移方程如下:

\(f_u=\max(dp_u+dp_v+w)\),其中 \(dp_u\) 不包括 \(dp_v\) 子树的长度。

那么这颗树的直径即为 \(\max \limits_{i=1}^n f_i\)。

其实 \(f\) 不用单独开数组,只需要在每次计算出后取最大值即可。

那怎么计算不包括子树 \(dp_v\) 的 \(dp_u\) 呢?

可以发现,子树 \(u\) 内的最大值即为所有的 \(dp_v+w\) 的最大值与次大值之和。那么又分两种情况:

  • 最大值在次大值之前被计算

在计算到次大值时,\(dp_u\) 为最大值,\(dp_u+dp_v+w\) 即为子树 \(u\) 最大值。

  • 次大值在最大值之前被计算

在计算到次大值时,\(dp_u\) 为次大值,\(dp_u+dp_v+w\) 即为子树 \(u\) 最大值。接下来 \(dp_u\) 就会更新成最大值。

于是就不用再排序了。

例2 洛谷-U81904

本题边权有负数,应使用树形 DP。

代码

3. 习题

Baekjoon-1167 翻译

本题链式前向星似乎不能通过,但邻接表可以通过。建单向边。

Baekjoon-1967 翻译

本题数据规模较小且没有负权值。建单向边。

标签:结点,子树,最大值,大值,DFS,问题,简单,树上,dp
From: https://www.cnblogs.com/lrxmg139/p/18012101

相关文章

  • dremio SchedulerService 服务简单说明
    SchedulerService内部调度服务算是一个比较重要的模块,比如dremio的功能都依赖此模块(元数据获取,一些数据清理任务,反射加速)参考实现子类SchedulerService实现也比较多,因为dremio集群中的节点有多种角色,为了保证数据的一致性会对于不同集群角色的节点进行不同的处理如下图......
  • 构建简单物体
    一.前言我们的空气曲棍球游戏已经取得了很大的进展,桌子已经放到了一个很好的角度,并且由于使用了纹理,更加好看了。然而,我们现在是用的点去代替木槌,它们实际看起来还不像木槌,许多应用都是通过合并简单的物体去构建更复杂的物体,我们在这篇文章中将学会如何绘制木槌以及桌子中间......
  • 代码问题汇总
    代码问题汇总不间断运行Python文件nohupnohup:是nohangup的缩写,在Linux系统下启动一个不会随着终端关闭而终止的命令使用场景:使用远程服务器运行程序,但是网络不稳定,一旦掉线运行就会终止,这时就需要使用nohup命令。#-u:设置Python解释器的缓冲模式为无缓冲(un......
  • PAT乙级-1008(数组元素循环右移问题)
    一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A0A1⋯A**N−1)变换为(A**N−M⋯A**N−1A0A1⋯A**N−M−1)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?输入格式:每个输入包......
  • 「UR#2」树上 GCD
    题目链接。讲的是一个较劣的做法。先转换成求\(\gcd\)为\(d\)倍数的种数。考虑无脑上根号分治。设阈值为\(B\),我们对不超过\(B\)的\(d\)暴力求。怎么求呢?我们有一个十分巧妙的方法,记录每个点子树与它距离为\(d\)的倍数的节点数,这样直接树上乱做一下就可以了,答案也是......
  • 如何利用内核跟踪点排查短时进程问题?
    在排查系统CPU使用率高的问题时,很可能遇到过这样的困惑:明明通过 top 命令发现系统的CPU使用率(特别是用户CPU使用率)特别高,但通过 ps、pidstat 等工具都找不出CPU使用率高的进程。这是什么原因导致的呢?一般情况下,这类问题很可能是以下两个原因导致的:第一,应用程序里面......
  • Rider 2023:打造高效.NET项目的智能IDE,让开发更简单mac/win版
    JetBrainsRider2023激活版下载是一款专为.NET开发者打造的强大集成开发环境(IDE)。这款IDE提供了丰富的功能,旨在帮助开发者更快速、更高效地编写、调试和测试.NET应用程序。→→↓↓载Rider2023mac/win版 Rider2023在保持了其一贯的智能代码补全、代码导航和重构工具的同......
  • Harmomy【问题系列篇】- ohpm : 无法将“ohpm”项识别为 cmdlet、函数、脚本文件或可
    ohpm:无法将“ohpm”项识别为cmdlet、函数、脚本文件或可运行程序的名称。造成该问题原因跟是:没有配置好ohpm的环境变量。问题1:配置环境变量左上角File->Settings,找到Ohpm放的路径配置环境变量重启DevEco,在Terminal输入ohpm-v,查看版本号结语希望本文章对遭遇同样问题......
  • go简单部署到ubuntu
    一、概述做了一个简单的服务用来下载文件,这里主要使用来下载apk,然后生成一个二维码给用户下载apk使用。 二、步骤1.在ubuntu上安装go环境并配置环境变量(网上一大堆)2.在Windows交叉打包一个可以运行在ubuntu上的可执行文件。打包命令file_download_service:可......
  • 简单的斐波那契数列通过chan实现生产者消费者模型
    1.实现斐波拉契数列写一个函数返回长度为n的斐波拉契slice数组funcfi(nint)[]int{ ifn<=0{ return[]int{} } fibs:=make([]int,n) fibs[0]=0 ifn>1{ fibs[1]=1 fori:=2;i<n;i++{ fibs[i]=fibs[i-1]+fibs[i-2] } } returnfibs}......