python coding with ChatGPT 专题1 | 树的直径

文章目录

  • 定义
  • 题目
    • 特点
  • 树的表示
    • 字典存储邻接表
    • TreeNode类
  • 深度优先 (两次DFS法)
  • 动态规划 (树形DP)
    • 优势
  • 相似题目
  • 参考资料

定义

树上任意两节点之间最长的简单路径即为树的「直径」。

题目

给定一棵树,求出这棵树的直径,即树上最远两点的距离。
包含n个结点,n-1条边的连通图称为树。
示例1的树如下图所示。其中4到5之间的路径最长,是树的直径,距离为5+2+4=11

在这里插入图片描述

输入:

edge_list = [[0,1],[1,5],[1,2],[2,3],[2,4]]
edge_value = [3,4,2,1,5]
n = 6

特点

一个没有固定根结点的树称为 无根树(unrooted tree)。无根树有几种等价的形式化定义:

  • 有 [n] 个结点, [n-1] 条边的连通无向图

  • 无向无环的连通图

  • 任意两个结点之间有且仅有一条简单路径的无向图

  • 任何边均为桥的连通图

  • 没有圈,且在任意不同两点间添加一条边之后所得图含唯一的一个圈的图

树的表示

字典存储邻接表

def get_tree(edge_list, edge_value, n):
    tree = {}
    for i in range(n):
        tree[i] = []
    for x, y in zip(edge_list, edge_value):
        tree[x[0]].append((x[1], y))
        tree[x[1]].append((x[0], y))
    return tree

TreeNode类

class TreeNode:
	def __init__(val):
		self.val = val
		self.neighbors = []
	
	def add_neighbor(self, node, weight):
		self.neighbors.append((node, weight))
def build_tree(edge_list, edge_value, n):
	nodes = [TreeNode(i) for i in range(n)]
	for (start, end), weight in zip(edge_list, edge_value):
		nodes[start].add_neighbor(end, y)
		nodes[end].add_neighbor(start, y)
	return nodes[0]

深度优先 (两次DFS法)

解决这个问题的一个有效方法是利用深度优先搜索(DFS)。这个方法可以分为两步来完成:

  • 从任意一个结点出发,执行一次深度优先搜索(DFS),找到距离它最远的结点。
  • 以步骤1中找到的结点作为起点,再次执行深度优先搜索(DFS),找到距离它最远的结点的距离,这个距离即为树的直径。

为什么这个方法有效?第一次DFS帮助我们定位到树的一端,然后第二次DFS从这一端出发能够找到最远的另一端,这就保证了我们计算出的距离是最长的路径。

在这里插入图片描述

dfs逻辑:

# simple dfs for dict
def simple_dfs(current_node, parent, tree)
	print(current_node)
	for node, _ in tree[current_node):
		if node != parent:
			simple_dfs(node)

# simple dfs for treenode
def simple_dfs(current_node, parent)
	print(current_node)
	for node _ in current_node.neighbors:
		if node != parent:
			simple_dfs(node)	

解题代码:

方法一:字典形式

# dict
def get_tree(edge_list, edge_value, n):
    tree = {}
    for i in range(n):
        tree[i] = []
    for x, y in zip(edge_list, edge_value):
        tree[x[0]].append((x[1], y))
        tree[x[1]].append((x[0], y))
    return tree
    
def dfs(current_node, parent, tree, distance):
	farthest_node = current_node
	max_distance = distance
	for node, weight in tree[current_node]:
		if node != parent:
			this_farthest_node, this_max_distance = dfs(node, current_node, tree, distance+weight)
			if this_max_distance > max_distance:
				max_distance = this_max_distance
				farthest_node = this_farthest_node
	return farthest_node, max_distance

def treeDiameter(edge_list, edge_value, n):
	tree = get_tree(edge_list, edge_value, n)
	farthest_node, _ = dfs(0, None, tree, 0)
	_, max_distance = dfs(farthest_node, None, tree, 0)
	return max_distance

方法二:TreeNode形式

class TreeNode:
    def __init__(self, val):
        self.val = val
        self.neighbors = []

    def add_neighbor(self, node, weight):
        self.neighbors.append((node, weight))


def build_tree(edge_list, edge_value, n):
    nodes = [TreeNode(i) for i in range(n)]
    for (start, end), weight in zip(edge_list, edge_value):
        nodes[start].add_neighbor(nodes[end], weight)
        nodes[end].add_neighbor(nodes[start], weight)
    return nodes[0]

def dfs(current_node, parent, distance):
    farthest_node = current_node
    max_distance = distance
    for node,weight in current_node.neighbors:
        if node != parent:
            this_farthest_node, this_max_distance = dfs(node, current_node, distance+weight)
            if this_max_distance > max_distance:
                farthest_node = this_farthest_node
                max_distance = this_max_distance
    return farthest_node, max_distance

def treeDiameter(edge_list, edge_value, n):
    current_node = build_tree(edge_list, edge_value, n)
    farthest_node, _ = dfs(current_node, None, 0)
    _, max_distance = dfs(farthest_node, None, 0)
    return max_distance

动态规划 (树形DP)

定义一个DP状态来表示从当前节点出发能够达到的最长路径长度
这个方法的关键在于,我们在遍历树的过程中,考虑通过这个节点的最长路径(也就是这个节点作为路径中间点,连接两个最长的子路径)。
在这里插入图片描述

def calculate_diameter(node, parent, diameter):
    max_depth1, max_depth2 = 0, 0  # 存储当前节点的最大和次大深度

    for neighbor, weight in node.neighbors:
        if neighbor == parent:
            continue

        # 获取到该邻接节点的最大深度
        depth = calculate_diameter(neighbor, node, diameter) + weight

        # 更新最大和次大深度
        if depth > max_depth1:
            max_depth2, max_depth1 = max_depth1, depth
        elif depth > max_depth2:
            max_depth2 = depth

    # 更新通过当前节点的最大直径
    diameter[0] = max(diameter[0], max_depth1 + max_depth2)

    # 返回到当前节点的最大深度
    return max_depth1

def treeDiameter(edge_list, edge_value, n):
    root = build_tree(edge_list, edge_value, n)
    diameter = [0]  # 使用列表作为引用传递,以便在递归中更新
    calculate_diameter(root, None, diameter)
    return diameter[0]

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

在这里插入图片描述

优势

通过树形DP,我们能够在一次遍历中完成这个计算,无需执行两次DFS。这种方法尤其在处理大型树结构时显示出其效率和优势。

相似题目

1245. 树的直径

参考资料

https://oi-wiki.org/graph/tree-diameter/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/499453.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue3+ts | axios 二次封装

安装 pnpm i axios axios 二次封装 // 实用性工具文件 放于 utils文件中 // 对axios函数库进行二次封装? // 二次封装的目的?利用axios请求、响应拦截器 import axios from axios// axios.create 创建一个axios实例:可以设置基础路径&a…

探索数据结构:链式队与循环队列的模拟、实现与应用

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:数据结构与算法 贝蒂的主页:Betty’s blog 1. 队列的定义 队列(queue)是一种只允许在一端进…

原来这就是线程安全(一)

TOC 一:什么是线程不安全?? 先看一段代码: public class Demo1 {public static int count 0;public static void main(String[] args) throws InterruptedException {Thread t1new Thread(()->{for (int i 0; i < 50000; i) {count;}});Thread t2new Thread(()-&g…

Linux-进程控制

&#x1f30e;进程控制【上】 文章目录&#xff1a; 进程控制 为什么要有地址空间和页表 程序的内存       程序申请内存使用问题 写时拷贝与缺页中断 父子进程代码共享       为什么需要写时拷贝       页表的权限位       缺页中断 退出码和错误码…

P3369 【模板】普通平衡树(splay 算法)

题目描述 您需要写一种数据结构&#xff08;可参考题目标题&#xff09;&#xff0c;来维护一些数&#xff0c;其中需要提供以下操作&#xff1a; 插入一个数 x。删除一个数 x&#xff08;若有多个相同的数&#xff0c;应只删除一个&#xff09;。定义排名为比当前数小的数的…

Pytorch从零开始实战22

Pytorch从零开始实战——CycleGAN实战 本系列来源于365天深度学习训练营 原作者K同学 内容介绍 CycleGAN是一种无监督图像到图像转换模型&#xff0c;它的一个重要应用领域是域迁移&#xff0c;比如可以把一张普通的风景照变化成梵高化作&#xff0c;或者将游戏画面变化成真…

2024软件设计师备考讲义——UML(统一建模语言)

UML的概念 用例图的概念 包含 <<include>>扩展<<exted>>泛化 用例图&#xff08;也可称用例建模&#xff09;描述的是外部执行者&#xff08;Actor&#xff09;所理解的系统功能。用例图用于需求分析阶段&#xff0c;它的建立是系统开发者和用户反复…

4G/5G防爆布控球

#防爆布控球 #远程实时监控 #移动应急指挥 #高清图像采集 #防爆安全认证 4G/5G防爆布控球 M130-EX防爆布控球是针对石化装置、石油平台、燃气、化工、制药、煤炭、冶炼、船舶制造、纺织等易燃易爆环境及危险场所而开发设计的防爆智能一体化电气设备。 产品型号&#xff1a;M13…

Antd Vue3 使用 Anchor 锚点组件记录

项目场景 客户要求做一个表单页面&#xff0c;表单数据分为三步&#xff0c;每一步骤是一个单独的 Vue 组件&#xff0c;表单上方需要使用锚点组件实现锚点定位到每一步的功能。 代码总览 <template><div class"guided-form-content-wrapper"><!-- …

CKS之Kubernetes审计日志

目录 概述 审计事件阶段 审计日志级别 None Metadata Request RequestResponse 审计日志的使用 步骤1&#xff1a;配置审计策略文件 步骤2&#xff1a;配置API Server 步骤3&#xff1a;配置日志存储 注意事项 审计策略与规则 审计日志样例 使用场景 概述 Kube…

一、JAVA集成海康SDK

JAVA集成海康SDK 文章目录 JAVA集成海康SDK前言一、项目依赖 jar1. examples.jar2. 项目依赖 jna.jar,可以通过 maven依赖到。二、集成SDK1.HcNetSdkUtil 海康 SDK封装类2.HCNetSDK3.Linux系统集成SDK三、总结前言 提示:首先去海康官网下载 https://open.hikvision.com/dow…

stable diffusion如何下载模型?

文件夹里面有14个模型&#xff0c;把这些模型复制到SD文件夹里 具体位置:SD文件>models>ControlNet

【C/C++】从零开始认识C++历程-启航篇

文章目录 &#x1f4dd;前言&#x1f320; 什么是C&#xff1f;&#x1f309;C的发展史 &#x1f320;C的重要性&#x1f309;语言的使用广泛度 &#x1f320;在工作领域&#x1f309; 岗位需求 &#x1f320;相关笔试题&#x1f309; 公司怎样面试C &#x1f6a9;总结 &#x…

蓝桥杯 - 小明的背包1(01背包)

解题思路&#xff1a; 本题属于01背包问题&#xff0c;使用动态规划 dp[ j ]表示容量为 j 的背包的最大价值 注意&#xff1a; 需要时刻提醒自己dp[ j ]代表的含义&#xff0c;不然容易晕头转向 注意越界问题&#xff0c;且 j 需要倒序遍历 如果正序遍历 dp[1] dp[1 - vo…

java的多态和final关键字

多态&#xff1a; 多态分为对象多态&#xff0c;行为多态 多态的前提&#xff1a; 有继承/实现关系&#xff1b;存在父类引用子类对象&#xff1b;存在方法重写&#xff1b; 注意&#xff1a;多态是对象&#xff0c;行为的多态&#xff0c;java的成员变量不谈多态 这是我写…

将Knife4j所展示请求参数和响应参数转化为TS类型声明

目标&#xff1a;在浏览器控制台输入js代码&#xff0c;将读取页面所展示的请求参数和响应参数&#xff0c;将他们转化为TS的类型声明&#xff0c;并在控制台中输出出来。 将Knife4j所展示请求参数和响应参数转化为TS类型声明 1 找到所需要的元素节点2 转化元素节点3 封装成函…

本地部署的stable diffusion 如何更新controlnet?

stable diffusion 未启动状态 点击“版本管理” 点击“扩展” 找到controlnet&#xff0c;点击右边的“更新”按钮 完成&#xff01;

【软考---系统架构设计师】特殊的操作系统介绍

目录 一、嵌入式系统&#xff08;EOS&#xff09; &#xff08;1&#xff09;嵌入式系统的特点 &#xff08;2&#xff09;硬件抽象层 &#xff08;3&#xff09;嵌入式系统的开发设计 二、实时操作系统&#xff08;RTOS&#xff09; &#xff08;1&#xff09;实时性能…

总结TCP各类知识点

前言 本篇博客博主将详细地介绍TCP有关知识点&#xff0c;坐好板凳发车啦~ 一.TCP特点 1.有连接 TCP传输的过程中类似于打电话的各个过程 2.可靠传输 通过TCP自身的多种机制来保证可靠传输 3.面向字节流 内容是以字节的方式来进行发送与接收 4.缓冲区 TCP有接收缓冲区…

网络安全接入认证-802.1X接入说明

介绍 802.1X是一个网络访问控制协议&#xff0c;它可以通过认证和授权来控制网络访问。它的基本原理是在网络交换机和认证服务器之间建立一个安全的通道&#xff0c;并要求客户端提供身份验证凭据。如果客户端提供的凭据是有效的&#xff0c;交换机将开启端口并允许访问。否则&…