【算法每日一练]-图论(保姆级教程篇16 树的重心 树的直径)#树的直径 #会议 #医院设置

目录

树的直径

题目:树的直径 (两种解法)

做法一: 

 做法二:

树的重心:

题目: 会议

 思路:

题目:医院设置 

思路:


        

        

树的直径

定义:树中距离最远的两个点之间的距离被称为树的直径。

一共有两种做法,先记结论,再给证明! 

做法一:

(1)任取一点作为起点x,找到距离该点最远的一个点y

(2)再找到距离y最远的一点z,那么y、z之间的路径就是一条直径。

做法二:

(1)距离直径上的一个点最远的点和次远的点一定是直径的两个顶点,所以我们只要能找到距离每一个点的最远距离和次远距离就能找到树的直径了。

做法一证明:核心是证明y一定是直径的一个端点。

使用反证法证明,假设xy是直径(x,y为直径上点),uv为非直径(u,v为非直径上点)。存在如下两种情况。

  • 第一种情况是两者相交,故意假设v是距离u最远的点,有以下推论:

    ua+av>ua+ay    =>    av>ay    =>     av+ax>ay+ax=xy

    假设不成立,因v可以代表任意一个不是直径上的点,故距离u最远的点一定是直径上的点!

  •  第二种情况是两者不相交,故意假设v是距离u最远的点,有以下推论:

    ua+av>ua+ab+by    =>    av > ab+by    =>    av+ab+bx>ab+by+ab+bx=2*ab+xy

    假设不成立,因v可以代表任意一个不是直径上的点,故距离u最远的点一定是直径上的点!

做法二证明:

前半句话不用……就不证明了吧,后半句“ 只要能找到距离每一个点的最远距离和次远距离就能找到树的直径了。” 意思就是把任意两点间的最长距离在某一点处砍成两半,当然有距离此点的最长距离和次长距离就是两头顶点间的最长距离,那么对所有点统计一下自然就找到直径长度了。

         

题目:树的直径 (两种解法)

spfa,dijkstra多用于跑有环的图,DAG图求最长距离直接dfs_dp就行!

做法一: 

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int tot,n,d[N],head[N];//d[i]表示到i点的距离
struct node{int to,w,nxt;}e[N*2];
void add(int u,int v,int w){e[++tot]=(node){v,w,head[u]};head[u]=tot;}void dfs(int u,int fa){for(int i=head[u];i;i=e[i].nxt){int v=e[i].to,w=e[i].w;if(v==fa)continue;d[v]=d[u]+w;//先更新再递归,因为d表示到u点的距离dfs(v,u);}
}
int main(){cin>>n;int u,v,w;for(int i=1;i<=n-1;i++){cin>>u>>v>>w;add(u,v,w);add(v,u,w);}dfs(1,0);//从任意点找最远距离的点int ans=-1;for(int i=1;i<=n;i++)if(d[i]>ans)ans=d[i],v=i;memset(d,0,sizeof(d));dfs(v,0);//此点必定在直径上,再跑一遍就完了for(int i=1;i<=n;i++)if(d[i]>ans)ans=d[i];cout<<ans;
}

 做法二:

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int ans=-1,tot,n,head[N];//d[i]表示到i点的距离
struct node{int to,w,nxt;}e[N*2];
void add(int u,int v,int w){e[++tot]=(node){v,w,head[u]};head[u]=tot;}int dfs(int u,int fa){int d1=0,d2=0;//d1是最长距离,d2是次长距离for(int i=head[u];i;i=e[i].nxt){int v=e[i].to,w=e[i].w;if(v==fa)continue;int d3=dfs(v,u)+w;//先更新距离if(d3>=d1) d2=d1,d1=d3;//如果是更长距离,最长和次长都更新else if(d3>d2)d2=d3;//如果仅比次长距离大,就仅更新次长距离}ans=max(ans,d1+d2);//最长距离加次长距离就是总长度return d1;//返回最长距离
}
int main(){cin>>n;int u,v,w;for(int i=1;i<=n-1;i++){cin>>u>>v>>w;add(u,v,w);add(v,u,w);}dfs(1,0);//从任意点开始cout<<ans;}

         

        

树的重心:

题目: 会议

         

 思路:

首先,阅读题目可以看出来,这道题目实际上就是求树的重心。

树的重心

定义:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,达到的效果是生成的多棵树尽可能平衡。

举个例子:

我们不妨设置d[i]表示以此点为根的所有点总距离和,cnt[i]表示以此为根的节点数

我们首先知道d[1]=16,cnt[1]=10我们来看d[2]应该怎么求,我们发现相对于d[1]来说,如果设2为最佳点,2,5,6其距离-1,剩下的1,4,3,7,8,9,10到其距离+1。

故:d[2]=d[1] - 3 + 7 =20

其中3是子根2对应的节点数cnt[2],7是1为子根对应的节点数cnt[1]-cnt[2]

得:d[i]=d[fa]-cnt[i]+(cnt[1]-cnt[i])

那么只需要先dfs求出来d[1]和每个点的cnt[i]。然后就可以进行dp最终求出所有点的d[i]。

#include <bits/stdc++.h>
using namespace std;
const int N=50005;
int minn=0x3f3f3f3f,ans,n,d[N],cnt[N];
vector<int>ve[N];
void dfs(int u,int fa,int len){//一定别走fa回去cnt[u]++;//先加上自己for(int i=0;i<ve[u].size();i++){int v=ve[u][i];if(v==fa)continue;dfs(v,u,len+1);//先求孩子的cnt,之后求自己cntcnt[u]+=cnt[v];}d[1]+=len;//最后求d[1]
}
void dp(int u,int fa){for(int i=0;i<ve[u].size();i++){int v=ve[u][i];if(v==fa)continue;d[v]=d[u]-2*cnt[v]+cnt[1];dp(v,u);//这里对自己进行转移更新,再对孩子的更新}
}
int main(){cin>>n;int a,b;for(int i=1;i<n;i++){cin>>a>>b;ve[a].push_back(b);ve[b].push_back(a);}dfs(1,0,0);dp(1,0);for(int i=1;i<=n;i++){if(d[i]<minn)minn=d[i],ans=i;}cout<<ans<<" "<<minn;
}

上面我打注释的地方一定要理解 

        

        

题目:医院设置 

思路:

还是一道求树的重心题。不过是每个点都有一个权值。那么把权值当成“另一个世界的节点数”就好了。然后不断求cnt,之后dp就行。 

#include <bits/stdc++.h>
using namespace std;
const int N=500;
int ans=0x3f3f3f3f,n,d[N],cnt[N],w[N];
vector<int>ve[N];
void dfs(int u,int fa,int len){cnt[u]=w[u];//这里还是先加自己for(int i=0;i<ve[u].size();i++){int v=ve[u][i];if(v==fa)continue;dfs(v,u,len+1);cnt[u]+=cnt[v];}d[1]+=len*w[u];//更新d[1]也要变一下
}
void dp(int u,int fa){for(int i=0;i<ve[u].size();i++){int v=ve[u][i];if(v==fa)continue;d[v]=d[u]+cnt[1]-cnt[v]*2;dp(v,u);}ans=min(ans,d[u]);
}
int main(){cin>>n;int c,a,b;for(int i=1;i<=n;i++){cin>>c>>a>>b;w[i]=c;//注意输入方式if(a)ve[i].push_back(a),ve[a].push_back(i);if(b)ve[i].push_back(b),ve[b].push_back(i);}dfs(1,0,0);dp(1,0);cout<<ans;
}

        

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

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

相关文章

科技革新背后:码垛机器人在不同领域的实践应用

随着科技的进步&#xff0c;机器人技术已经渗透到各个行业之中&#xff0c;成为提高生产效率、减少人工成本的重要工具。码垛机器人作为自动化技术的杰出代表&#xff0c;其在各个行业中的应用场景日益广泛&#xff0c;从食品饮料到化工产品&#xff0c;再到物流仓储&#xff0…

睿考网:注册会计师考试有年龄限制吗?

参加注册会计师考试是否有年龄限制&#xff1f;现行的规定并没有要求考生的年龄&#xff0c;所以只要符合既定的报名条件任何人都是可以参加的。 报名资格要求如下&#xff1a; 1. 报考者须为中国国籍公民&#xff0c;并且具备完全的民事行为能力。 2. 学历要求方面&#xf…

CSS的特殊技巧

1.精灵图 使用精灵图核心总结&#xff1a; 1. 精灵图主要针对于小的背景图片使用。 2. 主要借助于背景位置来实现--- background-position 。 3. 一般情况下精灵图都是负值。&#xff08;千万注意网页中的坐标&#xff1a; x轴右边走是正值&#xff0c;左边走是负值&#xf…

海康威视-AIOT的业务转型

海康威视的转型和定位为智能物联网&#xff08;AIoT&#xff09;解决方案和大数据服务的提供商。 公司不仅仅聚焦于其核心的视频监控业务&#xff0c;而且正在积极拓展到新的技术领域和市场。通过专注于物联感知、人工智能、大数据等技术的创新&#xff0c;对未来技术发展方向的…

生产计划数据模型,实现能源企业数字化高效管理

随着市场经济的快速发展&#xff0c;能源企业在经济发展中的地位也随之提高。但由于能源企业在生产计划经济管理上存在指标不平衡、市场观念落后和环保意识欠缺等问题&#xff0c;导致企业的经济效益降低。目前&#xff0c;提高企业的生产计划管理是改善能源企业现状最有利的途…

计算机网络:物理层下的传输媒体概览

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

MySQL---视图

目录 一、介绍 二、语法 三、视图的更新 四、视图作用 一、介绍 视图&#xff08;View&#xff09;是一种虚拟存在的表。视图中的数据并不在数据库中实际存在&#xff0c;行和列数据来自定义视图的查询中使用的表&#xff0c;并且是在使用视图时动态生成的。 通俗的讲&#…

Ambari——编译——解决解决windows和linux下phantomjs链接超时问题

您的支持是我继续创作与分享的动力源泉!!! 您的支持是我继续创作与分享的动力源泉!!! 您的支持是我继续创作与分享的动力源泉!!! 错误日志: [INFO] Copying extracted folder C:\Users\LENOVO\AppData\Local\Temp\phantomjs\phantomjs-2.1.1-windows.zip-extract-1786692…

『K8S 入门』三:资源调度

『K8S 入门』三&#xff1a;资源调度 一、Label 和 Selector 可以通过 Selector 基于 Label 匹配需要的资源 Label 标签 配置文件中&#xff08;metadata.labels&#xff09;配置 metadata: # Pod相关的元数据&#xff0c;用于描述Pod的数据name: nginx-demo #Pod的名称lab…

后端Jwt实现Token编码、解码以及axios的request请求头的Token传输方式

目录 一、什么是JWT&#xff1a; 二、Jwt的使用&#xff1a; 第一步&#xff1a;引入依赖&#xff1a; 第二步&#xff1a;配置拦截器&#xff1a;JwtInterceptor.java&#xff1a; 其中异常文件ServiceException配置如下&#xff1a; 全局异常文件GlobalException.java文…

利用Base64加密算法将数据加密解密

1. Base64加密算法 Base64准确来说并不像是一种加密算法&#xff0c;而更像是一种编码标准。 我们知道现在最为流行的编码标准就是ASCLL&#xff0c;它用八个二进制位&#xff08;一个char的大小&#xff09;表示了127个字符&#xff0c;任何二进制序列都可以用这127个字符表…

逻辑 | 逻辑先修营

学习到更新日期逻辑先修营-3常见逻辑连词及逻辑表达2024-3-23 1.形式逻辑基础1 2.形式逻辑基础2 3.常见逻辑连词及逻辑表述 4.OR相关考点 5.AND相关考点 6.逻辑箭头基本考点1 7.逻辑箭头基本考点2 8.代入逻辑推理事实真1 9.代入逻辑推理事实真2 10.形式逻辑四大基本考点…

【Entity Framework】 EF中DbContext类详解

【Entity Framework】 EF中DbContext类详解 一、概述 DbContext类是实体框架的重要组成部分。它是应用域或实例类与数据库交互的桥梁。 从上图可以看出DbContext是负责与数据交互作为对象的主要类。DbContext负责以下活动&#xff1a; EntitySet&#xff1a;DbContext包含…

Web前端—事件循环

事件循环 事件循环浏览器的进程模型何为进程&#xff1f;何为线程&#xff1f;浏览器有哪些进程和线程&#xff1f; 渲染主线程是如何工作的&#xff1f;若干解释何为异步&#xff1f;面试题&#xff1a;如何理解JS的异步&#xff1f;JS会阻碍渲染任务有优先级吗&#xff1f;面…

宜搭低代码高级认证实操题2 faas连接器加密解密

密钥维护页-保证有一条数据 敏感信息提交页 存档页&#xff0c;只是用来存数据的审批的时候不用这个表提交数据不然会出两条 授权查看页 FaaS连接器先下载好他的示例代码然后按照要求配置好参数直接拷贝进去就行 然后需要在云开发环境里面先new一个terminal然后跑一下./builde…

Leetcode - 周赛389

目录 一&#xff0c;3083. 字符串及其反转中是否存在同一子字符串 二&#xff0c;3084. 统计以给定字符开头和结尾的子字符串总数 三&#xff0c;3085. 成为 K 特殊字符串需要删除的最少字符数 四&#xff0c;3086. 拾起 K 个 1 需要的最少行动次数 一&#xff0c;3083. 字符…

如何在没有备份的情况下恢复 Android 上已删除的照片?

丢失 Android 设备上的珍贵照片可能是一场噩梦&#xff0c;尤其是在没有备份的情况下。无论是意外删除图像还是由于Android 崩溃而丢失图像&#xff0c;一想到它们可能会永远消失就令人沮丧。幸运的是&#xff0c;有多种方法可以在 Android 上恢复已删除的照片。 如何在没有备份…

一文打尽分布式系统中的事务处理!

之前分享了分布式事务的实现方案&#xff0c;今天我们来对比总结一下&#xff1a; 如何使用最大努力通知实现分布式事务&#xff1f;与本地消息表区别&#xff1f; 如何通过本地消息表实现分布式事务 用二阶段三阶段提交实现分布式事务 如何用TCC实现分布式事务&#xff1f…

上海晋名室外危化品暂存柜助力医药制造行业安全

近日上海晋名又有两台室外危化品暂存柜项目通过验收&#xff0c;此次项目主要用于医药制造行业次氯酸钠、乙醇消毒剂、甲醛等化学品的室外暂存安全。 用户单位创立于2003年&#xff0c;是一家以从事医药制造业为主的企业。用户在日常工作运营中涉及到次氯酸钠、乙醇消毒剂、甲…

MT2191 整数大小比较(高精度)

给出两个正整数&#xff0c;判断他们的大小。 输入格式&#xff1a; 两个正整数。 输出格式&#xff1a; 若前者大&#xff0c;输出>&#xff1b; 若后者大&#xff0c;输出<&#xff1b; 若一样大&#xff0c;输出。 输入&#xff1a; 1412894619244619891 23762842…