树的直径与重心【2024蓝桥杯0基础】-学习笔记

本文介绍了如何利用深度优先搜索算法计算树的直径,包括代码模板,并讨论了树的重心性质及其求解方法。作者通过实例分析和感悟,强调了模拟过程在解决问题中的重要性。
摘要由CSDN通过智能技术生成

树的直径

树的直径是树上最长的一条链,当然这条链不唯一,所以一棵树可能有多条直径。直径由两个顶点u,v决定,若有一条直径(u,v),则满足以下性质:

  • u,v的度数均为1(叶子节点)
  • 在以任意一个点为根的树上,u,v中必然存在一个点作为最深的叶子结点。
  • 深度就是点距离根节点的距离
    利用上述性质求直径长度:
    第一遍DFS使用点1找到最深的点u(多个则随机选一个),然后从u出发做第二遍DFS找到最深的点v(多个则随机选个即可),得到的<u,v>即为一条直径上述方法要求边权值不为负,负权则利用树形DP求解

例题分析

在这里插入图片描述

直径代码模板

import sys
#深搜最好都要加一下
sys.setrecursionlimit(100000)
input = sys.stdin.readline
def dfs(u, fa, pre = None):
    global S#设置最深叶节点的索引
    if d[u] > d[S]:
        S = u
    for v, w in G[u]:
        if v == fa:
            continue
        #记录节点的深度,w是路径的长度
        d[v] = d[u] + w
        #因为第一遍遍历的不是直径,我们要从第二遍叶子节点开始记录
        if pre:
            pre[v] = u
        dfs(v,u,pre)
n = int(input())
#记录树
G = [[] for i in range(n + 1)]
#记录深度(路径的权重和)
d = [0] * (n + 1)
#记录路径上的节点
pre = [0] *(n + 1)
for _ in range(n - 1):
    u, v, w = map(int, input().split())
    G[u].append([v, w])
    G[v].append([u, w])

S = 1
#从根节点开始遍历到叶子节点
dfs(1, 0)
d[S] = 0
#以叶子节点为根,遍历到另外一个叶子节点
dfs(S, 0, pre)
#记录路径的权重和
L = d[S]
#获取直径所在的边
L_list = set()
#如果没有遍历到根节点就一直循环
#寻找直径上面的所有点
while S != 0:
    L_list.add(S)
    S = pre[S]
for u in L_list:
    for i, (v, w) in enumerate(G[u]):
        if v in L_list:
            G[u][i] = [v, w - 1]
S = 1
dfs(1, 0)
d[S] = 0
#边的权重减去一之后的路径权重和
dfs(S, 0)
L2 = d[S]
print(L)
#公共边的路径长度
print(L - L2)

树的重心

在这里插入图片描述

性质分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
利用性质1求树的重心

代码复现

import sys
sys.setrecursionlimit(100000)
input = sys.stdin.readline
#mss[x]表示x的所有子树,包括父节点大小的最大值
#sz数组统计每个子树的大小
def dfs(u, fa):
    for v in G[u]:
        if v == fa:
            continue
        dfs(v, u)
        #统计每个点的子树的节点个数
        sz[u] +=sz[v]
        mss[u] = max(mss[u],sz[v])
    mss[u] = max(mss[u], n - sz[u])

n = input()
G = [[] for i in range(n + 1)]
sz = [0] * (n + 1)
mss = [0] * (n + 1)
for _ in range(n - 1):
    u, v = map(int, input().split())
    G[u].append(v)
    G[v].append(u)
dfs(1, 0)
root = mss.index(min(mss[1:]))

感悟

还是多模拟这个过程你就知道代码的奥妙了!啊哈哈哈

蓝桥杯云课学习笔记分享,欢迎大佬们批评指正!

一直在进步就好咯!

by 闻不多

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值