当前位置: 首页 > news >正文

算法 之 树形dp 树的中心、重心

文章目录

    • 重心实践题目
      • 小红的陡峭值

  • 在树的算法中,求解树的中心和重心是一类十分重要的算法

求解树的重心

  • 树的重心的定义:重心是树中的一个节点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点称为树的重心
  • 求解重心需要记录的值:由于重心关注的是删除一个节点之后,剩余的连通分支中点的最大值,然后这个值要求是最小的,然后需要返回这个最小化的最大值。
  • 删除一个节点之后,会分为几个部分,节点u的所有子树所独立出来的子树,以及原本的树删除以u为根节点的树
  • 所以要记录,u的所有子树当中,size子树的最多节点数,sumnunm以u为根节点的节点数(用于dfs的返回值),n-sumnum除去以u为根节点的剩余部分的节点数
  • 值得注意的是,遍历的之后是从根节点到叶子节点,但是我们是在归(叶子节点到根节点)中的过程中,更新答案的
  • 由于是 无向图,所以要么设置vis[i]标记节点是否访问过,要么设置dfs(u,fa)其中fau的父亲节点

在这里插入图片描述

在这里插入图片描述

  • c代码
    在这里插入图片描述

在这里插入图片描述

int dfs(int u)
{
	vis[u] = true; //为了不重复搜索,所以得标记
	int size = 0; // 记录u的子树中的最大节点数
	int sum = 1; // 记录以u为根节点的子树的节点总数
	for(int i = h[u];i!=-1;i=ne[i])
	{
		int j = e[i];
		if (vis[j]) continue;
		int s = dfs(j);
		size = max(size,s);
		sum += s;
	}
	ans = min(ans,max(size,n-sum));
	return sum;
}

  • python 代码
# 使用邻接表来存储点之间的边关系
g = [[]*n ]
vis = [False]*n
ans = n
def dfs(u): 
	global ans
	vis[u] = True
	sumnum = 1 # 记录以u为根节点的子树的总节点数
	size = 0 # 记录 u的子树当中最大的节点数
	for v in g[u]:
		if vis[v]: continue # 如果访问过就跳过
		s = dfs(v) # 求解出以v为根节点的子树的节点数
		size = max(size,s) # 更新答案
		sumnum += s
	# 更新这个ans
	ans = min(ans,max(size,n-sumnum))  
	return sum
	 

重心实践题目

小红的陡峭值

小红的陡峭值

在这里插入图片描述
在这里插入图片描述

  • 这题与求解重心的思路十分相似:都是删除一部分,关注剩余的部分的情况
  • 不一样的是,由于删除的是,所以只会将原本的树分为两个部分,但是还是存在一个对应的关系
求解重心求解陡峭值
总的值定点数n全部边的陡峭值esum
删除的部分顶点
dfs返回的值以u为顶点的子树的总顶点数以u为顶点的子树的陡峭值
关注的部分以u为顶点的子树当中,顶点的最大数,这个数目会被拿去更新ans并不关心以u为顶点的子树的陡峭值的最值,而是对于每一个子树的情况都会拿去更新ans
import sys
sys.setrecursionlimit(10 ** 6)
n = int(input())
g = [[] for _ in range(n+1)]

# 类似于求解这个 重心的问题,问题的关键在于从根到叶子,同时在叶子返回这个根的时候动态更新答案
esum = 0
for i in range(n-1):
    u,v = map(int,input().split())
    g[u].append(v)
    g[v].append(u)
    esum += abs(u-v)

ans = float("inf")
vis = [False]*(n+1)

def dfs(u):
    global ans
    vis[u] = True
    # 需要记录以u为根的陡峭值,以及子树的陡峭值
    sumnum = 0
    for v in g[u]:
        if vis[v]: 
            continue
        s = dfs(v)
        sumnum += abs(u-v) + s 
        # 更新答案
        ans = min(abs(esum-abs(u-v)-s-s),ans)
    return sumnum
dfs(1)
print(ans)

相关文章:

  • 深入理解序列并行化:sp_size 与批量大小参数详解
  • git安装(windows)+vscode配置
  • 深入理解C语言链表:数据结构的基石
  • 注意力机制-学习
  • QML界面卡死分析--01 --Canvas与QRasterPaintEngine
  • Python:函数(一)
  • 【DDD的本质与核心思想】
  • 脚本学习(1)验证目录自动化生成脚本
  • 在rocklinux里面批量部署安装rocklinx9
  • mysql的锁--一篇读懂所有锁机制
  • C语言:确定进制
  • 多宠识别:基于计算机视觉的智能宠物管理系统架构解析
  • k8s启动时calico-kube-controllers与coredns组件一直是pending状态
  • 《 C++ 点滴漫谈: 三十 》函数参数
  • OpenCV实现视频背景提取
  • Go 语言封装 HTTP 请求的 Curl 工具包
  • 数据分析与AI丨AI Fabric:数据和人工智能架构的未来
  • 实现多语言适配
  • 在线程间共享数据_《C++并发编程》第三章笔记
  • 【Linux系统编程】基本IO函数
  • 莱布雷希特专栏:古典乐坛边缘人
  • 杨国荣︱以经验说事:思想史研究中一种需要反思的现象
  • 永久基本农田竟沦为垃圾场,湖南湘潭回应:全面启动专项整治
  • 被央视曝光“废旧厂区沦为垃圾山”,江西萍乡成立调查组查处
  • 复旦建校120周年大型义诊举行,百余名专家服务市民超三千人次
  • 哪条线路客流最大?哪个站点早高峰人最多?上海地铁一季度客流报告出炉