树的重心-java

主要通过深度优先搜索来完成树的重心,其中关于树的重心的定义可以结合文字多加理解。

文章目录

前言☀

一、树的重心☀

二、算法思路☀

1.图用邻接表存储

2.图的遍历

3.算法思路 

二、代码如下☀

1.代码如下:

2.读入数据

3,代码运行结果

总结


前言☀

主要通过深度优先搜索来完成树的重心,其中关于树的重心的定义可以结合文字多加理解。


提示:以下是本篇文章正文内容,下面案例可供参考

一、树的重心☀

给定一颗树,树中包含 n 个结点(编号 1∼n)和 n−1 条无向边。

请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。

重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中结点数的最大值最小,那么这个节点被称为树的重心。

输入格式

第一行包含整数 n,表示树的结点数。

接下来 n−1行,每行包含两个整数 a 和 b,表示点 a 和点 b 之间存在一条边。

输出格式

输出一个整数 m,表示将重心删除后,剩余各个连通块中点数的最大值。

数据范围

1≤n≤100000

二、算法思路☀

1.图用邻接表存储

我们通过一个链表数组来存储,我们把数组中每一个链表的起点对应图中的一个结点,然后与该结点相连的结点,挂在数组中对应起始结点的后面即可,图示如下:

图1.1图邻接表存储 

我们引入一维整型数组e,存储链表里面的各个结点的值;一维整型数组ne里面存储结点的下一个结点在数组e里面的索引值;整型变量index表示新创建结点在e数组中的下标。

一位整型数组head用来存储图中的每个节点,head[i]表示以i结点为起点的单链表的头结点,链表中的每一个结点都是与i相连的结点,如图1.1所示。故head数组里面的值初始化为-1,表示此时链表都为空。

我们新创建的结点值为b即e[index] = b;然后将新创建的结点头插法插入,即将原本头结点后的所有结点链接到新结点后面即ne[index] = head[a];然后再将头结点指向新创建的结点head[a] = index。注意让index++,保证index一直指向新创建的结点。

    //添加边//头插法public static void add(int a,int b){e[index] = b;ne[index] = head[a];head[a] = index++;}

关于单链表的基本操作还有不明白的可以去看我的单链表-java-CSDN博客 这篇博客,里面有对单链表操作的各种详细介绍。

2.图的遍历

无向图是特殊的有向图,树也是特殊的图,故我们只需要考虑有向图即可。 

 

图2.1深度优先遍历示例图 

深度优先遍历其实就是一条路走到尽头,每当我们走过一个结点会设置一个标记表示已经走过了。当我们走到尽头无法再走时就回退到上一个结点,然后从该结点看看有无其它没走过的路径,无路可走时再回退到上一个结点,所有结点都被走过后就完成了深度优先遍历。依次走过的结点顺序如图2.1的黄色数字描述的顺序一致。

 

图2.2广度优先遍历示例图

 广度优先遍历也叫层序遍历,我们一层一层逐层遍历。可以通过队列模拟,将根结点入队;当队列不为空,弹出结点,然后再将与该结点相连的结点一次入队,重复上述操作,直到队列为空,就遍历的所有的结点。

遍历的顺序如图2.2模拟所示,黄色数字表示层数。

3.算法思路 

 图3.1样例模拟

图3.2删除结点1连通块情况 

图3.3删除结点2连通块情况 

图3.4删除结点4各个连通块情况 

树的重心:删除一个结点后,剩下的连通块中结点个数最多但是在删除各个结点的连通块中的结点数最小的,那么这个结点就是树的重心。通过上述图3.1-3.4的示例,即我们删除1结点连通块中结点最多是4,删除结点2连通块中结点最多是6,删除结点4连通块中结点最多是5,等等,我们可以知道结点1就是树的重心。

图3.5示例图 

 我们用深度优先搜索dfs来确定根节点u的结点的个数;当前结点遍历过设置为flag[u] = true;然后用整型变量sum来统计结点的个数,初始化为1(根节点本身),然后访问与u相连的边,如果没有被访问过,就接着对该边进行dfs深度优先搜索,然后更新为删除这一节点后所剩的连通图的结点数目的最大值;将sum加上子树的结点个数就是以u为根节点的结点的个数。

比较删除u后的u子树中最大的连通块(6,3-9中的更大者),和整个树减u子树剩下的连通块(1-2-8-5-7)
 res = Math.max(n - sum,res)。

sum:表示以这一点为根结点的树中所有结点个数
res:表示删除这一点后的连通块中结点数目的最大值(不断更新)
ans:表示所有(依次删除每个结点的情况)最大连通结点数目的最小值,即各个res的最小值(不断更新)
所有备注可结合上方图示一起看

    //深度优先搜索//以u为根节点的结点的个数public static int dfs(int u){//当前点被搜过了flag[u] = true;//存储以u为结点int sum = 1;//存储当前删掉某个结点后最大连通子图的个数int res = 0;//访问u的子节点for(int i = head[u];i != -1;i = ne[i]){int j = e[i];if(!flag[j]){int s = dfs(j);res = Math.max(s,res);//以u为根结点的树结点数量=1+它各个子树的结点数量sum += s;}}// 比较删除u后的u子树中最大的连通块(6,3-9中的更大者),和整个树减u子树剩下的连通块(1-2-8-5-7)res = Math.max(n - sum,res);//所有最大的连通块结点数目找到最小值ans = Math.min(ans,res);return sum;}

二、代码如下☀

1.代码如下:


import java.io.*;
import java.util.Arrays;
import java.util.Scanner;public class 树的重心 {static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static int N = 100010,M = N * 2;//记录头结点static int[] head = new int[N];//存储结点的值static int[] e = new int[M];//存储当前结点的下一个结点的索引值static int[] ne = new int[M];//最新创建的结点的索引即数组e中空最新的空结点的索引static int index;//用来存储结点是否被遍历过了static boolean[] flag = new boolean[N];static int n;static int ans = N;public static void main(String[] args) {Scanner sc = new Scanner(br);n = sc.nextInt();Arrays.fill(head,-1);for (int i = 0;i < n - 1;i++){int a = sc.nextInt();int b = sc.nextInt();add(a,b);add(b,a);}dfs(1);pw.print(ans);pw.flush();}//深度优先搜索//以u为根节点的结点的个数public static int dfs(int u){//当前点被搜过了flag[u] = true;//存储以u为结点int sum = 1;//存储当前删掉某个结点后最大连通子图的个数int res = 0;//访问u的子节点for(int i = head[u];i != -1;i = ne[i]){int j = e[i];if(!flag[j]){int s = dfs(j);res = Math.max(s,res);//以u为根结点的树结点数量=1+它各个子树的结点数量sum += s;}}res = Math.max(n - sum,res);//所有最大的连通块结点数目找到最小值ans = Math.min(ans,res);return sum;}//添加边public static void add(int a,int b){e[index] = b;ne[index] = head[a];head[a] = index++;}
}

2.读入数据

9
1 2
1 7
1 4
2 8
2 5
4 3
3 9
4 6

3,代码运行结果

4

总结

这次多看一下图示,理解各变量的意义,代码是简介,其中的意思要多加理解。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电机控制系列模块解析(28)—— 其他功能概述

其他功能概述 软件侧&#xff1a;观测器估计发散保护、时序异常检测 主电路侧&#xff1a;IGBT结温估算、直流母线电容容值估算 电机侧&#xff1a;电机温度估计、轴承异常估计、电机退磁检测 负载侧&#xff1a;负载不平衡检测、掉载检测、负载惯量自适应 上述各项功能&a…

新书推荐:2.2.4 第11练:消息循环

/*------------------------------------------------------------------------ 011 编程达人win32 API每日一练 第11个例子GetMessage.c&#xff1a;消息循环 MSG结构 GetMessage函数 TranslateMessage函数&#xff1a;将虚拟键消息转换为字符消息 DispatchMessage函数…

信息系统项目管理师0148:输出(9项目范围管理—9.3规划范围管理—9.3.3输出)

点击查看专栏目录 文章目录 9.3.3 输出 9.3.3 输出 范围管理计划 范围管理计划是项目管理计划的组成部分&#xff0c;描述将如何定义、制定、监督、控制和确认项 目范围。范围管理计划用于指导如下过程和相关工作&#xff1a; ①制定项目范围说明书&#xff1b;②根据详细项目范…

【机器学习】XGBoost: 强化学习与梯度提升的杰作

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 XGBoost: 强化学习与梯度提升的杰作引言1. XGBoost概览1.1 什么是XGBoost&#…

纷享销客安全体系:安全运维运营

安全运维运营(Security Operations,SecOps)是指在信息安全管理中负责监控、检测、响应和恢复安全事件的一系列运营活动。它旨在保护组织的信息系统和数据免受安全威胁和攻击的损害。 通过有效的安全运维运营&#xff0c;组织可以及时发现和应对安全威胁&#xff0c;减少安全事…

09.2手工制作docker镜像-kod服务

手工制作docker镜像-kod服务 基于centos6.9系统镜像&#xff0c;搭建kod服务&#xff0c;提交镜像 创建并进入容器 添加centos6系统的yum源和epel源 yum源 curl -o /etc/yum.repos.d/CentOS-Base.repo https://www.xmpan.com/Centos-6-Vault-Aliyun.repo epel源 curl -o /e…

定时器的使用和实现

目录 一.定时器Timer类的主要方法 二.定时器Timer类的使用 三.定时器的模拟实现 一.定时器Timer类的主要方法 定时器Timer类在java.util包中。 使用前先进行实例化&#xff0c;然后使用实例的schedule(TimerTask task, long delay)方法&#xff0c;设定指定的任务task在指…

python数据分析-心脏瓣膜手术风险分析与预测

研究背景 人的心脏有四个瓣膜&#xff0c;主动脉银、二尖、肺动脉和三尖源 不管是那一个膜发生了病变&#xff0c;都会导致心脏内的血流受到影响&#xff0c;这就是通常所说的心脏期膜病&#xff0c;很多是需要通过手术的方式进行改善的。随着人口老龄化的加剧,&#xff0c;心…

8. 正则表达式

正则表达式 在处理字符串时&#xff0c;需要查找符合某些复杂规则的字符串&#xff0c;正则表达式就是用于描述这些规则的工具 一、正则表达式语法 行定位符&#xff1a;用来描述字符串的边界 -->用来匹配一整行 符号匹配位置^行的开始$行的结尾 ^tm : 可以匹配行 tm equa…

高质量 HarmonyOS 权限管控流程

高质量 HarmonyOS 权限管控流程 在 HarmonyOS 应用开发过程中&#xff0c;往往会涉及到敏感数据和硬件资源的调动和访问&#xff0c;而这部分的调用就会涉及到管控这部分的知识和内容了。我们需要对它有所了解&#xff0c;才可以在应用开发中提高效率和避免踩坑。 权限管控了…

19、Go Gin框架集成Swagger

介绍&#xff1a; Swagger 支持在 Gin 路由中使用一系列注释来描述 API 的各个方面。以下是一些常用的 Swagger 注释属性&#xff0c;这些属性可以在 Gin 路由的注释中使用&#xff1a; Summary: 路由的简短摘要。Description: 路由的详细描述。Tags: 用于对路由进行分类的标…

数据挖掘--数据仓库与联机分析处理

什么是数据仓库 &#xff08;面集时非&#xff09; 面向主题的&#xff1a;围绕某一主题来构建集成的&#xff1a;图片文字杂糅在一起时变的&#xff1a;随时间变化的数据非易失的&#xff1a;硬盘存放&#xff0c;不易丢失 操作数据库系统&#xff08;OLTP)与数据仓库(OLAP…

MySQL将错乱的水果信息,截取展示为 品名 英文名 价格 三列展示

将错乱的水果信息&#xff0c;截取展示为 品名 英文名 价格 三列展示 idname1苹果Apple72Plum6李子3Pineapple8菠萝4Mango5芒果5龙吐珠5Buddha’sHand6Olive9橄榄7Raspberry4树莓8Apricot5杏子9Grapefruit9柚子10火龙果Dragonfruit911倒挂金钟Hanging6LobsterClaw12巨峰葡萄Co…

AI办公自动化:批量把docx文档转换为txt文本

任务&#xff1a;把docx文档批量转换成txt&#xff0c;首先让deepseek写了一段代码&#xff0c;但是转换失败。用的是最流行的python-docx库来读取docx文档&#xff0c;但是始终无法读取成功&#xff0c;换成pywin32库就解决问题了。 在deepseek中输入提示词&#xff1a; 写一…

【背包-BM70 兑换零钱(一)】

题目 BM70 兑换零钱(一) 描述 给定数组arr&#xff0c;arr中所有的值都为正整数且不重复。每个值代表一种面值的货币&#xff0c;每种面值的货币可以使用任意张&#xff0c;再给定一个aim&#xff0c;代表要找的钱数&#xff0c;求组成aim的最少货币数。 如果无解&#xff0c;…

docker 命令 ps,inspect,top,logs详解

docker常用命令教程-4 docker ps docker ps 命令用于列出当前正在运行的容器。默认情况下&#xff0c;它只显示正在运行的容器&#xff0c;但你可以使用 -a 或 --all 选项来显示所有容器&#xff08;包括已停止的容器&#xff09;。 常用的选项和示例&#xff1a; -a 或 --…

【C语言题解】1、写一个宏来计算结构体中某成员相对于首地址的偏移量;2、写一个宏来交换一个整数二进制的奇偶位

&#x1f970;欢迎关注 轻松拿捏C语言系列&#xff0c;来和 小哇 一起进步&#xff01;✊ &#x1f308;感谢大家的阅读、点赞、收藏和关注 &#x1f495;希望大家喜欢我本次的讲解&#x1f495; 目录&#x1f451; 1、写一个宏&#xff0c;计算结构体中某变量相对于首地址的偏…

UE4获取动画序列资产的动画时长

谢谢”朝闻道“大佬的指点~

(UE4.26)UE4的FArchive序列化入门

前言 序列化(Serialize)和反序列化(UnSerialize)是程序领域常见的概念。对于这两个词汇我理解的是 序列化(Serialize): 变量值(int, float, string等基本类型, 或者Array&#xff0c;Map&#xff0c;或者更复杂的复合体)存储为一个文件(二进制流, 二进制文件, json, xml等格式…

C++并发之互斥(std::mutex)

目录 1 概述2 使用实例3 接口使用3.1 mutex3.2 lock3.3 try_lock3.4 unlock1 概述 互斥锁是一个可锁定的对象,用于在代码的关键部分需要独占访问时发出信号,防止具有相同保护的其他线程同时执行并访问相同的内存位置。   互斥对象提供独占所有权,不支持递归性(即,线程不…