图论之求树的重心

文章目录

  • 题目
  • 简要分析
  • 解题思路
  • 代码实现

题目

原题链接:https://www.acwing.com/problem/content/848/

题目描述
给定一颗树,树中包含 n 个结点(编号 1∼n)和 n−1条无向边。请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。

输入格式
第一行包含整数 n,表示树的结点数。
接下来 n−1 行,每行包含两个整数 a 和 b,表示点 a和点 b之间存在一条边。

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

数据范围
1≤n≤105 (n大于等于1,小于等于10的5次方)

输入样例

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

输出样例

4

先画出题目中的树:
请添加图片描述

简要分析

根据题目的描述,树的重心就是指删除树中的某一个结点后剩余各个连通子树的结点数目的最大值最小。下面来分析一下:

若删除结点1,则剩余三个连通子树,很容易看出中间那颗子树的结点数目最多有4个,所以剩下的最大连通子树的结点数目为4
若删除结点2,则剩余两个结点数目为1的子树和一个结点数目为6的子树,即剩下的最大连通子树的结点数目为6
若删除结点3,则剩余一个结点数目为1的子树和一个结点数目为7的子树,即剩下的最大连通子树的结点数目为7
若删除结点4,则剩余一个结点数目为3的子树和一个结点数目为5的子树,即剩下的最大连通子树的结点数目为5

一直往下枚举就可以得出删除结点1后剩下的最大连通子树的结点数目最小,也就是说结点1就是树的重心。

解题思路

根据分析可以知道必须要把树中的全部结点都枚举一遍才能才能算出哪个结点是树的重心,所以需要对树进行深搜dfs
请添加图片描述
如果删除结点4,下面蓝色部分是结点4的子树,根据题目已经知道树的总结点数为n,所以只需要算出蓝色部分(结点4的子树)结点数目sum,同时算出最大子树的结点数size,就可以算出上面蓝色部分(连通树)的结点数目n-sum,再比较n-sum和size的大小,得出剩下的最大连通子树的结点数目。

在这里插入图片描述

题目要求的是将重心删除后,输出剩余子树的最大连通子树的结点数目,所以用深搜dfs算出每个结点删除后剩下的最大连通子树的结点数目,然后再比较出最小值即可。

代码实现

树是一种特殊的图(无向图),存储图有邻接矩阵法,邻接表法,链式邻接表法和链式前向星法等,这里选择的是邻接表法来存储图,由于树是无向图,所以存储边的时候正反两条都得存。

存储图得代码实现:

#include<iostream>
#include<cstring>
using namespace std;const int N=1e5+10;数据范围是10的5次方
//以有向图的格式存储无向图,所以每个节点至多对应2n-2条边
int e[2*N];//e[i]的值是编号,是下标为i节点的编号。
int ne[2*N];//ne[i]的值是下标,是下标为i的节点的next节点的下标。
int h[2*N];//h[i]存储的是下标,是编号为i的节点的next节点的下标,比如编号为1的节点的下一个节点是4,那么我输出e[h[1]]就是4
int idx;单链表指针(下标)
bool vis[2*N];//记录节点是否被访问过,访问过则标记为true
int n;//n个节点
int ans=N;//表示重心的所有的子树中,最大的子树的结点数目//a所对应的单链表中插入b  a作为根
void add(int a,int b)
{e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}int main()
{memset(h,-1,sizeof(h));//初始化h数组 -1表示尾节点memset(vis,0,sizeof(vis));//初始化vis数组,都还没访问过cin >> n;// 树中是不存在环的,对于有n个节点的树,必定是n-1条边for(int i=1;i<n;i++){int a,b;cin >> a >> b;add(a,b);add(b,a);//存储无向图}//打印邻接表for(int i=1;i<=n;i++){cout << i;for(int j=h[i];j!=-1;j=ne[j]){cout <<  "->" << e[j];}cout << "\n";}return 0;
}

运行结果:
在这里插入图片描述

在这里插入图片描述
接下来就是深搜dfs,任取一点u,若以u为重心,则分为两类:一类是以u为根节点的子树,一类是根节点u上面的部分。需要计算出以u为根节点的最大子树的结点数和u上面的部分的结点数,然后取二者最大值即可。还要定义一个布尔数组(bool)vis记录每个结点是否访问过,如果已经访问过,就无需再访问,避免向上查找。

从根到叶,再从叶回到根,总是在返回时收集子树的信息(这里是结点的数目),从小到大更新每个结点的信息size[u],sum[u],更新ans。

因为u是任取的一点,所以在遍历每个点是都会得到一个ans,只需要取最小值即可。

AC代码

#include<iostream>
#include<cstring>
using namespace std;const int N=1e5+10;数据范围是10的5次方
//以有向图的格式存储无向图,所以每个节点至多对应2n-2条边
int e[2*N];//e[i]的值是编号,是下标为i节点的编号。
int ne[2*N];//ne[i]的值是下标,是下标为i的节点的next节点的下标。
int h[2*N];//h[i]存储的是下标,是编号为i的节点的next节点的下标,比如编号为1的节点的下一个节点是4,那么我输出e[h[1]]就是4
int idx;单链表指针(下标)
bool vis[2*N];//记录节点是否被访问过,访问过则标记为true
int n;//n个节点
int ans=N;//表示重心的所有的子树中,最大的子树的结点数目//a所对应的单链表中插入b  a作为根
void add(int a,int b)
{e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}int dfs(int u)
{vis[u]=true;//标记u这个点被搜过int sum=1;//记录以u为根的子树的结点数,根结点也要包含,所以初始化为1int size=0;//记录以u为根的最大子树的结点数for(int i=h[u];i!=-1;i=ne[i])//i是边的编号{int j=e[i];//j是u的邻接点if(vis[j]) continue;//避免向上查找int g=dfs(j);//g是以j为根的子树的结点数size=max(size,g);//记录以u为根的最大子树的结点数sum+=g;//累加以u为根的各个子树的结点数}int sump=max(size,n-sum);//最大连通子树的结点数目ans=min(ans,sump);//更新答案,找到删除每个结点后的最大连通子树的结点数目的最小值//ans=min(ans,max(size,n-sum));//更新答案return sum;
}
int main()
{memset(h,-1,sizeof(h));//初始化h数组 -1表示尾节点memset(vis,0,sizeof(vis));//初始化vis数组,都还没访问过cin >> n;// 树中是不存在环的,对于有n个节点的树,必定是n-1条边for(int i=1;i<n;i++){int a,b;cin >> a >> b;add(a,b);add(b,a);//存储无向图}dfs(1);//任取一个点,开始深搜cout << ans << "\n";return 0;
}

对以上内容有异议的欢迎大家来讨论,希望对大家有帮助,多多支持哦,以后也会更新有关算法的内容

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

钉钉 ai卡片 stream模式联调

sdk连接 新建卡片模板下载node.js sdkconfig.json 配置应用信息 启动项目npm i npm run build npm run start连接成功 获取卡片回调 注册卡片回调事件调用https://api.dingtalk.com/v1.0/card/instances 创建卡片实例&#xff0c;返回实例Id //参数结构 {"cardTempla…

Linux文件与相关函数的知识点1

Open函数 高频使用的Linux系统调用&#xff1a;open write read close Linux 自带的工具&#xff1a;man手册&#xff1a; man 1是普通的shell命令&#xff0c;比如ls 调用命令&#xff1a;man 1 ls man 2是系统调用函数&#xff0c;比如open&#xff0c;write 调用open…

AV1技术学习:Quantization

量化是对变换系数进行&#xff0c;并将量化索引熵编码。AV1的量化参数 QP 的取值范围是0 ~ 255。 一、Quantization Step Size 在给定的 QP 下&#xff0c;DC 系数的量化步长小于 AC 系数的量化步长。DC 系数和 AC 系数从 QP 到量化步长的映射如下图所示。当 QP 为 0 时&…

MySQL的高可用(MHA)

高可用模式下的故障切换&#xff0c;基于主从复制。 单点故障和主从复制不能切换的问题。 至少需要三台。 故障切换过程0-30秒 vip地址&#xff0c;根据vip地址所在的主机&#xff0c;确定主备。 主 vip 备 vip 主和备不是优先级确定的&#xff0c;主从复制的时候就确定…

BGP之选路MED

原理概述 当一台BGP路由器中存在多条去往同一目标网络的BGP路由时&#xff0c;BGP协议会对这些BGP路由的属性进行比较&#xff0c;以确定去往该目标网络的最优BGP路由。BGP路由属性的比较顺序为Preferred Value属性、Local Preference属性、路由生成方式、AS_Path属性、Origin属…

一款简而轻的项目运维监控软件,支持低侵入式在线构建、自动部署、日常运维(附源码)

前言 在当今快速发展的软件开发领域&#xff0c;开发团队经常面临一系列运维挑战。没有专业运维人员的支持&#xff0c;开发人员不得不承担构建和部署项目的任务。 面对不同项目的构建和部署命令&#xff0c;以及多环境的打包需求&#xff0c;开发人员需要一个能够简化这些流…

算法 day4 【双指针、快慢指针、环形链表】链表下

⚡刷题计划day4继续&#xff0c;可以点个免费的赞哦~ 下一期将会开启哈希表刷题专题&#xff0c;往期可看专栏&#xff0c;关注不迷路&#xff0c; 您的支持是我的最大动力&#x1f339;~ 目录 ⚡刷题计划day4继续&#xff0c;可以点个免费的赞哦~ 下一期将会开启哈希表刷题…

C# 匿名函数与Lambda表达式

本文仅作学习笔记与交流&#xff0c;不作任何商业用途&#xff0c;作者能力有限&#xff0c;如有不足还请斧正 1.匿名函数 在 C# 中&#xff0c;匿名函数是一种没有名称的函数&#xff0c;可以直接在代码中定义和使用 匿名函数主要有两种形式&#xff1a;匿名方法和Lambda 表…

Modbus转EtherCAT网关将Modbus协议的数据格式转换为EtherCAT协议

随着工业自动化技术的快速发展&#xff0c;不同通信协议之间的互操作性变得越来越重要。Modbus作为一种广泛使用的串行通信协议&#xff0c;与以太网为基础的EtherCAT协议之间的转换需求日益增长。本文将从网关功能、硬件设计、性能以及应用案例来介绍这款Modbus转EtherCAT网关…

TinaLinux ssh 环境搭建

adb shell passwd root #修改密码 vim /etc/ssh/sshd_config #编辑SSH配置文件/etc/ssh/sshd_config&#xff0c;根据需要配置如端口、允许登录的用户等 切换为英文输入法输入i&#xff0c;将下面PermitRootLogin和PasswordAuthentication改成yes PermitRootLogin yes…

华媒舍:6个媒体宣发套餐,快速突破传播界限

在当今信息爆炸的社会中&#xff0c;有效地传播自己的信息变得愈发困难。特别是对于媒体宣发来说&#xff0c;如何在市场竞争激烈的情况下突破传播界限&#xff0c;让自己的消息传达给更多的人&#xff0c;这是每个企业和个人都面临的难题。 为了解决这个问题&#xff0c;我们推…

MSPM0GXX单片机内部比较器深度解析

目录 0 前言1 简介1.1单片机简介1.2 比较器简介 2 比较器运行原理2.1 比较器配置2.2 比较器通道选择2.3 比较器输出2.4 输出滤波器2.5 采样输出模式2.6 消隐模式2.7 基准电压发生器2.8 窗口比较器模式2.9 比较器滞后 3 比较器的优势 0 前言 本文仅以TI公司生产的MSPM0GXX单片机…

【BUG】已解决:You are using pip version 10.0.1, however version 21.3.1 is available.

You are using pip version 10.0.1, however version 21.3.1 is available. 目录 You are using pip version 10.0.1, however version 21.3.1 is available. 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#…

【Django】 读取excel文件并在前端以网页形式显示-安装使用Pandas

文章目录 安装pandas写views写urls安装openpyxl重新调试 安装pandas Pandas是一个基于NumPy的Python数据分析库&#xff0c;可以从各种文件格式如CSV、JSON、SQL、Excel等导入数据&#xff0c;并支持多种数据运算操作&#xff0c;如归并、再成形、选择等。 更换pip源 pip co…

Word 导入导出

在实际的开发过程中&#xff0c;也会遇到导入导出的功能&#xff0c;今天就简单的做一下总结。 1.需求&#xff1a;将下面word 数据导入到数据库并进行存储 在Controller中 RequestMapping(value "/ImportWord")public RawResponseBodyObject ImportWord(HttpServl…

VBA技术资料MF178:将某个文件夹中的图片导入Word

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

基于微信小程序图书馆座位预约管理系统设计与实现

1.1选题动因 当前的网络技术&#xff0c;软件技术等都具备成熟的理论基础&#xff0c;市场上也出现各种技术开发的软件&#xff0c;这些软件都被用于各个领域&#xff0c;包括生活和工作的领域。随着电脑和笔记本的广泛运用&#xff0c;以及各种计算机硬件的完善和升级&#x…

开源模型也能强过闭源?Llama 3.1-405B数值对标GPT4!

Llama 3.1-405B引起AI浪潮&#xff1a;开源模型也能强过闭源&#xff1f; Llama 3.1 就这几天&#xff0c;只要你有在关注AI相关的事&#xff0c;你就会看见一群人在讨论 Meta 新出的 Llama 3.1。外网无数的业内大佬都在为之疯狂&#xff0c;因为 Llama3.1-405B 成为了目前开源…

CefSharp音视频编译与免费下载

注&#xff1a;Cefharp 音频和视频播放编译&#xff0c;生成相应的dll文件&#xff0c;从而支持项目开发。 建议编译至少 16G 的 RAM和至少 250G 的 SSD。该脚本以 E 盘为例&#xff0c;您需要在 E 盘上手动创建 cef 文件夹。禁止在转载后通过发布其他平台向用户收取下载费用。…

JavaEE - Spring Boot 简介

1.Maven 1.1 什么是Maven 翻译过来就是: Maven是⼀个项⽬管理⼯具。基于POM(Project Object Model,项⽬对象模型)的概念&#xff0c;Maven可以通 过⼀⼩段描述信息来管理项⽬的构建&#xff0c;报告和⽂档的项⽬管理⼯具软件。 可以理解为&#xff1a;Maven是一个项目管理工具…