【算法】图论——树的重心

目录

题目解析

算法原理

图的存储

算法实现 


题目解析

题目解析 

给定一颗树,树中包含n个结点(编号)和n-1条无向边。请找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。


什么是重心? 

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


补充:树和图的关系 

树本质上是一种特殊的图,它对应的是无环连通图。也就是说,在树中任意两个节点之间都存在路径(连通性),并且不存在回路(无环)。

树与一般图相比,有着如下性质:

  • 一般的图可以有环,节点之间的连接关系比较复杂。比如在一个有向图中,边是有方向的,从一个节点到另一个节点的路径可能受到边的方向限制;而树作为无向图,边没有方向限制,并且由于其无环的特性,从任意节点到另一个节点的路径是唯一的。
  • 从连通性角度看,树是保持图连通的最小结构。如果从树中去掉任何一条边,就会导致图不再连通,会划分出两个或更多的连通分量;而对于一般的连通图,可能存在冗余的边,去掉某些边后仍然可以保持连通。

重心举例

如下图,我们得到一个树结构:

 

若我们删除节点1,那么我们会得到三个连通图,如下:

  • 所谓的各个连通块中节点的最大值,指的是连通块之间的对比,在上图中,连通块节点数量最大值是4,即中间的连通块节点数量

重心是指我们遍历这张图中所有的节点,并尝试删除节点后所形成连通块节点数量的最大值是最小的。

举一个非重心的例子:如下图

 我们尝试删除节点2后,所形成的连通图一共有如下3个:

 很明显,连通块节点数量的最大值是6。

而尝试删除1的连通块节点数量的最大值是4,所以2一定不是树的重心

实际上,在上图中一共存在着两个重心,它们分别是1和4,感兴趣可以自己尝试算算


树的重心的性质 

  • 树中所有点到某个点的距离和中,到重心的距离和是最小的,如果有两个距离和,他们的距离和一样。
  • 删除重心后所得的所有子树,节点数不超过原树的1/2,一棵树最多有两个重心;
  • 把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上。
  • 一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。
  • 一棵树最多有两个重心,且相邻。 

算法原理

我们要求得一棵树得重心,那么较为简单得一种方式是尝试计算每一个节点如果被删除后,所得的连通块数量的最大值,并取计算完后的最小值。

下图删除节点4为例,思考一下,若删除节点4后,所形成的连通块有哪些?

 

很明显,连通块只会出现在两种情况:

  • 根节点为4的树的所有子树都是连通块
  • 整棵树的根,刨除4这个子树所形成的连通块

那么如何获得根节点为4的树的所有子树的节点数量,以及4所对应的树的节点数量呢

我们只需DFS即可:

  • 遍历到9,9无子树,向上返回1
  • 遍历到3,3的子树的连通块节点数量为1,那么3对应的连通块节点数量就为2,3向上返回2
  • 遍历到6,6无子树,向上返回1
  • 遍历到4,4的子树的连通块节点数量为2+1=3,所以4对应的连通块中节点数量为3+1=4(包含4自身)

如何获得整棵树的根(抛出删除节点4对应子树)的连通块数量呢?

直接通过n-i计算即可

其中n表示的是总的节点数量,在上图中n即为9。

其中i表示的是以被删除节点为根的子树的连通块数量,在上图中i即为4


图的存储

图的存储我们采用邻接表

  • 邻接表是图(包括有向图和无向图)的一种链式存储结构。它主要用于存储图中节点之间的连接关系。
  • 对于图中的每个顶点,都有一个单链表,链表中的节点存储了与该顶点相邻接的顶点信息

举例 

假设,值为1的点指向了2、4、7。那么我们只需要构建一个单链表,表头节点是1,其余的表示的是1指向它

若每一个节点都有一张单链表,用来表示它所指向的元素,那么该存储结构我们称之为邻接表

若是无向图,那么当1指向2时,还需要添加一条2指向1的边


单链表的实现

#include <iostream>
using namespace std;const int N = 1e5 + 10;
int ne[N], e[N], idx;
//ne存储的是next指针指向的节点编号
//e存储的是节点编号所对应的值
//idx用于分配一个唯一的节点编号int main()
{int n; //n是节点的数量cin >> n;//下标为0的点是头节点ne[0] = -1;//初始化单链表,-1来表示空节点idx = 1; //节点编号从1开始,因为0已经分配给头节点了for (int i = 0; i < n; ++i){int x;cin >> x;e[idx] = x; //分配一个节点编号给x ne[idx] = ne[0];//当前节点指向头节点指向的节点ne[0] = idx++;//头节点指向当前节点}for (int i = ne[0]; i != -1; i = ne[i]) printf("%d ", e[i]);return 0;
}

邻接表的实现 

#include <iostream>
using namespace std;const int N = 1e5 + 10;int h[N], ne[N], e[N], idx;void add(int a,int b)
{//1 3 表示1指向3,即h[1]头插3//添加一条a->b的边e[idx] = b;ne[idx] = h[a];h[a] = idx++;
}int main()
{int n; //边的数量cin >> n;memset(h, -1, sizeof h); //初始化邻接表for (int i = 0; i < n; ++i){int a, b;cin >> a >> b;add(a, b), add(b, a);}return 0;
}

算法实现 

第一步:根据题目要求,我们首先把输入进来的无向图保存起来,题目的输入如下:

  • 第一行:输入的是n
  • 第2-n行:输入两个数字a,b。表示a和b之间有一条无向边 

具体代码参考邻接表的实现

第二步:深度优先遍历

dfs中有一个参数u在dfs期间我们也一并更新最终的结果,定义变量ans表示最终的返回值

dfs函数要完成的功能是获得以u为根的子树形成的连通块节点数量,并更新根节点ans

注意:由于每一个节点我们只需要遍历一次,所以我们定义一个bool数组st,若st[i]=true,表示该节点已经被遍历过了,反之未遍历过

#include <iostream>
using namespace std;const int N = 1e5 + 10;int h[N], ne[N], e[N],st[N], idx;
int ans = N,n; //n表示边的数量 ,ans表示删除结果void add(int a,int b)
{e[idx] = b;ne[idx] = h[a];h[a] = idx++;
}
int dfs(int u)
{int res = 0; //res表示删除点u后连通块节点数量最大值int sum = 1; //sum表示要返回给上一层的以u为根的子树节点数量,初始化为1因为至少有u一个节点for (int i = h[u]; i != -1; i = ne[i]){int j = e[i];if (!st[j]){st[j] = true;int s = dfs(j);res = max(res, s); //连通块节点数量最大值可能出现在子树中sum += s;st[j] = false;}}res = max(res, n - sum); //最大值可能出现在根节点抛去u子树后的连通块节点数量ans = min(res, ans); //u可能是重心,更新一下return sum;
}
int main()
{cin >> n;memset(h, -1, sizeof h); //初始化邻接表for (int i = 0; i < n-1; ++i){int a, b;cin >> a >> b;add(a, b), add(b, a);}dfs(1);printf("%d", ans);return 0;
}

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

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

相关文章

全面UI组件库Telerik 2024 Q4全新发布——官方宣布支持.NET 9

Telerik DevCraft包含一个完整的产品栈来构建您下一个Web、移动和桌面应用程序。它使用HTML和每个.NET平台的UI库&#xff0c;加快开发速度。Telerik DevCraft提供最完整的工具箱&#xff0c;用于构建现代和面向未来的业务应用程序&#xff0c;目前提供UI for ASP.NET MVC、Ken…

数据分析(一): 掌握STDF 掌握金钥匙-码农切入半导体的捷径

中国的半导体行业必然崛起&#xff01;看清这个大势&#xff0c;就会有很多机会。 今天&#xff0c;我们一起来了解一下半导体行业的一朵金花&#xff1a;STDF。 实际上这只是一种文件格式&#xff0c;但是当你熟练掌握解析这种文件的时候&#xff0c;你就已经打开在这个基础…

【批处理脚本】更改Windows系统中的 hosts 解析文件

概述 作用 修改 Windows 系统中的 hosts 文件&#xff0c;可以实现 插入 或 删除 条目。该脚本允许用户以管理员权限执行&#xff0c;将特定的域名解析到指定的 IP 地址 应用场景 非常适用于需要频繁或批量修改 hosts 文件的场景&#xff1a; 屏蔽网站、域名重定向、DNS 污染防…

【Rust在WASM中实现pdf文件的生成】

Rust在WASM中实现pdf文件的生成 前言概念和依赖问题描述分步实现pdf转Blob生成URL两种方式利用localstorage传递参数处理图片Vec<u8>到pdf格式的Vec<u8>使用rust创建iframe显示pdf的Blob最后 前言 实现了一个通用的前端jpg转pdf的wasm,因为动态响应框架无法直接打…

CanFestival移植到STM32 F4芯片(基于HAL库)

本文讲述如何通过简单操作就可以把CanFestival库移植到STM32 F4芯片上&#xff0c;作为Slave设备。使用启明欣欣的工控板来做实验。 一 硬件连接 观察CAN报文需要专门的设备&#xff0c;本人从某宝上买了一个兼容PCAN的开源小板子&#xff0c;二十几块钱&#xff0c;通过USB接…

Cursor+Devbox AI开发快速入门

1. 前言 今天无意间了解到 Cursor 和 Devbox 两大开发神器,初步尝试以后发现确实能够大幅度提升开发效率,特此想要整理成博客以供大家快速入门. 简单理解 Cursor 就是一款结合AI大模型的代码编辑器,你可以将自己的思路告诉AI,剩下的目录结构的搭建以及项目代码的实现均由AI帮…

Redis常见问题总结

Redis常见问题总结 1.Redis分布式存储方案 分布式存储核心特点主从&#xff08;Master/Slave&#xff09;模式一主多从&#xff0c;故障时手动切换。哨兵&#xff08;Sentinel&#xff09;模式有哨兵的一主多从&#xff0c;主节点故障自动选择新的主节点。集群&#xff08;Cl…

Svn如何切换删除账号

记录Svn清除切换账号 1.首先打开小乌龟的设置如下图 打开设置后单击已保存数据&#xff0c;然后选择清除 接上图选择清除后&#xff0c;就可以打勾选择清除已保存的账号&#xff0c;我们再次检出的就可以切换账号了 &#x1f449;总结 本次记录Svn清除切换账号 如能帮助到你…

电子应用设计方案-38:智能语音系统方案设计

智能语音系统方案设计 一、引言 智能语音系统作为一种便捷、自然的人机交互方式&#xff0c;正逐渐在各个领域得到广泛应用。本方案旨在设计一个高效、准确、功能丰富的智能语音系统。 二、系统概述 1. 系统目标 - 实现高准确率的语音识别和自然流畅的语音合成。 - 支持多种语…

红外跟随避障模块详解

在智能车、机器人和自动化等领域避障技术是确保安全和高效运行的关键。红外避障模块作为一种常见的避障解决方案&#xff0c;因其非接触、响应速度快和抗干扰能力强等优点而备受青睐。本文将详细介绍红外避障模块的特点、工作原理、以及应用案例&#xff0c;帮助您更好地了解这…

数据下载实践教程系列:跨过数据获取障碍---TCIA和TCGA数据下载

1.前言 作为一个医工交叉领域的工科学者&#xff0c;我想你必定听说过TCGA数据库和TCIA数据库&#xff0c;但是身边不少生信学者和医生是会用的&#xff0c;但大都将此作为护城河而讳莫如深&#xff01;有了数据&#xff0c;工科小伙伴也可以摆脱数据依赖而独立进行研究了。作为…

期权懂|场内个股期权开户流程有哪些?

期权小懂每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 场内个股期权开户流程有哪些&#xff1f; 场内个股期权开户第一步开户‌&#xff1a; 投资者首先需要在具有期权交易资格的证券公司开立期权账户。 ‌场内个股期权开户第二步选…

Qt复习学习

https://www.bilibili.com/video/BV1Jp4y167R9/?spm_id_from333.999.0.0&vd_sourceb3723521e243814388688d813c9d475f https://subingwen.cn/qt/qt-primer/#1-4-Qt%E6%A1%88%E4%BE%8B https://subingwen.cn/qt/ https://download.qt.io/archive/qt/1.1Qt的特点 1.2QT中的…

Qt开源控件:图像刻度轴绘制器 (附源码)工程项目私信博主

项目简介 图像刻度轴绘制器是一款基于 Qt/C 开发的小型绘图工具&#xff0c;旨在实现带有刻度轴的图像显示功能。该项目主要用于需要精确测量或标注图像坐标的场景。通过左侧和底部的坐标轴以及对应的刻度线&#xff0c;可以直观地了解图像内容在二维空间中的位置。 项目功能 …

【Transformer序列预测】Pytorch中构建Transformer对序列进行预测源代码

Python&#xff0c;Pytorch中构建Transformer进行序列预测源程序。包含所有的源代码和数据&#xff0c;程序能够一键运行。此程序是完整的Transformer&#xff0c;即使用了Encoder、Decoder和Embedding所有模块。源程序是用jupyterLab所写&#xff0c;建议分块运行。也整理了.p…

mac 安装python3和配置环境变量

mac 安装python3和配置环境变量 前言怎样选择python3的版本python3的安装1、去官网下载安装包2、下载完成后直接解压,检查安装是否成功 前言 在学习python的第一步就是安装它和配置他的环境变量&#xff0c;那么选择哪个版本的python你可曾知道&#xff0c;下面就讲解怎样选择…

基于MFC实现的人机对战五子棋游戏

基于MFC实现的人机对战五子棋游戏 1、引言 此报告将详细介绍本次课程设计的动机、设计思路及编写技术的详细过程&#xff0c;展现我所学过的C知识以及我通过本次课程设计所学到例如MFC等知识。在文档最后我也会记录我所编写过程遇到的问题以及解决方案。 1.1 背景 五子棋是…

6.824/6.5840 Lab 4: Fault-tolerant Key/Value Service

We are the champions my friend And well keep on fighting till the end We are the champions ——We Are The Champions 完整代码见&#xff1a; GitHub - SnowLegend-star/6.824: As we advance, the trials grow ever more arduous, and now we stand before an even mig…

ShardingSphere 数据库中间件

数据库中的数据量猛增&#xff0c;访问性能也变慢了&#xff0c;优化迫在眉睫 ? 1. 关系型数据库本身比较容易成为系统瓶颈&#xff1a;单机存储容量、数据库连接数、处理能力都有限。 2. 当单表的数据量达到 1000W 或 100G 以后&#xff0c;由于查询维度较多&#xff0c;即使…

Webpack Tree Shaking 技术原理及应用实战,优化代码,精简产物

前言 在前端开发中&#xff0c;优化代码体积和提升应用性能是至关重要的课题。Webpack 提供了多种优化手段来帮助开发者实现这一目标&#xff0c;Tree Shaking 就是其中一种非常重要的优化技术&#xff0c;它通过在编译阶段移除未被使用的代码模块&#xff0c;从而显著减小最终…