【算法每日一练]-图论(保姆级教程篇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…

nginx配置ssl支持https的详细步骤

nginx配置ssl支持https的详细步骤 文章概要&#xff1a;在建站的时候我们通常要让网站通过https进行访问&#xff0c;不然使用http过程中&#xff0c;所有信息都是未加密的&#xff0c;并且用户访问的时候浏览器会屏蔽我们的网站。本文介绍如何通过nginx配置ssl以支持通过https…

CSS的特殊技巧

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

Spring设计模式-实战篇之策略模式 + 工厂模式

案例&#xff1a;使用策略模式和工厂模式优化大量的if-else 原先代码如下&#xff0c;有衣服、零食、蔬菜三种类型的商品&#xff0c;并且每一类满减折扣不一样&#xff0c;如果使用if-else&#xff0c;代码会显得非常冗长&#xff0c;并且大量的if-else很容易眼花导致维护代码…

Mybatis DAO开发

使用Mybatis开发Dao&#xff0c;通常有两个方法&#xff0c;即 原始Dao开发方法Mapper代理开发方法 原始DAO开发方式 原始Dao开发方法需要程序员编写Dao接口和Dao实现类&#xff0c;无非就是在Dao实现类里面调用映射文件里面定义的sql而已。 工具类 package org.example.u…

海康威视-AIOT的业务转型

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

ptx指令,抽象指令与架构

&#xff08;没用的问题&#xff1a;ptx如何抽象sass&#xff0c;它创造ir的方式和结果与mlir 创造ir有什么区别吗&#xff1f;&#xff09; PTX操作数类型&#xff1a; 寄存器操作数&#xff1a;在PTX中&#xff0c;寄存器用于存储临时数据&#xff0c;并在指令之间传递值。寄…

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

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

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

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

MySQL---视图

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

Git常用指令总结

Git常用指令总结 下载git&#xff0c;这个不需要交的&#xff01;&#xff01;&#xff01; 1、初始化自己的git仓库 git config --global user.name “Your name” 配置自己的用户名 git config --global user.email “mailexample.com” 配置邮箱 git config --global c…

blender记一下法线烘焙

这里主要记一下使用cage的方式 原理 看起来是从cage发射射线&#xff0c;打中高模了就把对应uv那个地方的rgb改成打中的点的normal的rgb 正事 那么首先需要一个高模 主要是几何要丰富 无所谓UV 然后一个低模&#xff0c;既然上面提到UV&#xff0c;那低模就要展UV, 展完之后…

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个字符表…

hbuilderX打包vue项目白屏问题以及element-ui的icon图标无法正常显示问题

附录一&#xff1a;hbuilderX打包vue项目白屏问题 将项目目录下的config文件夹里的index.js文件中,将build对象下的assetsPublicPath中的“/”&#xff0c;改为“./”后&#xff0c;再打包生成的 dist 文件 build: { // assetsPublicPath: /,//修改前 assetsPublicPa…

逻辑 | 逻辑先修营

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

C语言-指针问题-排序问题

题目描述 输入 10 个整数&#xff0c;将他们从小到大排序后输出&#xff0c;并给出每个元素在原来序列中的位置. 将程序需要的代码补全&#xff0c;只提交 begin 到 end 部分的代码。 #include <stdio.h> #define N 10int main() {int a[N], b[N], cnt 1, i, j, tmp;…