树的直径两种求法

article/2025/10/7 0:02:54

首先先介绍一下什么是树的直径,树的直径就是树中所有最短路经距离的最大值。

求树的直径通常有两种方法,一种是通过两次搜索(bfs和dfs均可),另一种就是通过树形dp来求了。

先来介绍一下用两次深搜来求树的直径:

先从图上任意一点,搜索整棵树,找到距离该点最远的点,再用距离该点最远的点搜索一次,即可得到树的直径。

现在来给出证明:

图像说明,两个椭圆形代表抽象子树,使得结论具有一般性:

由直径的定义我们可以知道由直径的一个端点搜索出的最大距离一定是直径的长度,那么我们现在就要证明由图中随机的一个点搜索出来的最远点一定是直径的一个端点,下面主要用反证法来证明。

以下图形均假设e1 e2为直径两端点

第一种情况,我们一开始所选取的点在直径上

我们一开始选定的点是e0,假如通过e0搜到的距离最远的点是e3,则说明

d(e0,o)+d(o,e3)>= d(e0,o)+d(o,e2),等价于

d(o,e3)>= d(o,e2)则 d(e1,o)+d(o,e3)>= d(e1,o)+d(o,e2)这与e1,e2是直径的两个端点矛盾,故不成立

第二种情况:我们一开始所选取的点不在直径上,且e0与e3与直径不相交,设直径上的o点与e0,e3路径上的e4点相交

则d(e0,e4)+ d(e4,e3)>= d(e0,e4)+ d(e4,o)+d(o,e2)

等价于 d(e4,e3)>= d(e4,o)+d(o,e2)

则d(e1,o)+  d(o,e4)+ d(e4,e3)>=d(e1,o)+ d(o,e2)

这与e1,e2是直径的两个端点矛盾,故不成立

最后一种情况:我们一开始所选取的点不在直径上,且e0与e3与直径相交,不妨设交点为o

则d(e0,o)+d(o,e3)>= d(e0,o)+d(o,e2),等价于

d(o,e3)>= d(o,e2)则 d(e1,o)+d(o,e3)>= d(e1,o)+d(o,e2)

 这与e1,e2是直径的两个端点矛盾,故不成立

希望大家好好理解这个图,在以后的很多关于树的直径的题目中的结论证明方法都类似于上面的证明方法。

核心代码:

void dfs(int x,int father)
{for(int i=h[x];i!=-1;i=ne[i])//用链式前向星存树{int j=e[i];if(j==father) continue;//树是一种有向无环图,只要搜索过程中不返回父亲节点即可保证不会重复遍历同一个点。d[j]=d[x]+w[i];//更新每个点到起始点的距离(在树中任意两点的距离是唯一的)dfs(j,x);//继续搜索下一个节点}
}

ll ans=-1;for(int i=1;i<=n;i++)if(d[i]>ans){ans=d[i];e=i;记录与搜索点距离最远的点}

下面我来介绍一下树形dp来求树的直径:

不难想到,距离直径上的一个点最远的点和次远的点一定是直径的两个顶点,所以我们只要能找到距离每一个点的最远距离和次远距离不就能找到树的直径了么,但是有一点需要注意,就是距离一个点的最远距离和次远距离不能与重合部分。下面我来对具体实现方面展开说明。

我们需要开两个数组F1[]和F2[]分别记录到某个点的最远距离和次远距离,这样我们最后把每个点的两个数组相加取个最大值就可以找到树的直径了。

核心代码:

void dp(int x,int father)
{for(int i=h[x];i!=-1;i=ne[i])链式前向星存树{int j=e[i];if(j==father) continue;//防止原路返回dp(j,x);//dp过程应该是由叶节点开始的,也就是说先递归到叶节点再开始进行状态转移if(f1[x]<f1[j]+w[i])//如果子节点的最大距离+子节点与父节点之间边的权重大于父节点的最大距离,那么父节点的最大距离和次大距离都要得到相应更新{f2[x]=f1[x];f1[x]=f1[j]+w[i];}else if(f2[x]<f1[j]+w[i])//若子节点的最大距离+子节点与父节点之间边的权重小于父节点的最大距离,再判断与父节点的次大距离的关系f2[x]=f1[j]+w[i];ans=max(ans,f1[x]+f2[x]);//在搜索过程中找到树的直径}
}

下面我将给出一道例题,并用两种方法给出解答:

After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to get more exercise, so he has committed to create a bovine marathon for his cows to run. The marathon route will include a pair of farms and a path comprised of a sequence of roads between them. Since FJ wants the cows to get as much exercise as possible he wants to find the two farms on his map that are the farthest apart from each other (distance being measured in terms of total length of road on the path between the two farms). Help him determine the distances between this farthest pair of farms.

Input

* Lines 1.....: Same input format as "Navigation Nightmare".

Output

* Line 1: An integer giving the distance between the farthest pair of farms.

Sample Input

7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S

Sample Output

52

我大概简化下题意吧:就是先输入两个整数,第一个整数表示点的数量,第二个整数表示边的数量,下面给出每条边的起始点和终止点以及该边的权值和方向(具体方向是用不到的,计算机中的方向只需考虑始点与终点即可),求该树的直径。

代码1(dfs)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N=1000013;
typedef long long ll;
ll h[N],ne[N],e[N],idx,d[N],w[N];
bool vis[N];
void add(int x,int y,int z)
{e[idx]=y;w[idx]=z;ne[idx]=h[x];h[x]=idx++;
}
void dfs(int x,int father)
{for(int i=h[x];i!=-1;i=ne[i])//用链式向前星存树{int j=e[i];if(j==father) continue;//树是一种有向无环图,只要搜索过程中不返回父亲节点即可保证不会重复遍历同一个点。d[j]=d[x]+w[i];//更新每个点到起始点的距离(在树中任意两点的距离是唯一的)dfs(j,x);//继续搜索下一个节点}
}
int main()
{int n,m,e;cin>>n>>m;memset(h,-1,sizeof h);char c[2];int x,y,z;while(m--){scanf("%d%d%d%s",&x,&y,&z,c);add(x,y,z);add(y,x,z);}dfs(1,0);ll ans=-1;for(int i=1;i<=n;i++)if(d[i]>ans){ans=d[i];e=i;}memset(d,0,sizeof d);dfs(e,0);for(int i=1;i<=n;i++)if(d[i]>ans)ans=d[i];printf("%lld",ans);return 0;
}

代码2(树形dp)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=1e6+10;
int n,m;
long long ans;
long long e[N],h[N],ne[N],idx,w[N];
long long f1[N],f2[N];
void add(int x,int y,int z)
{e[idx]=y;w[idx]=z;ne[idx]=h[x];h[x]=idx++;
}
void dp(int x,int father)
{for(int i=h[x];i!=-1;i=ne[i]){int j=e[i];if(j==father) continue;//防止原路返回dp(j,x);if(f1[x]<f1[j]+w[i]){f2[x]=f1[x];f1[x]=f1[j]+w[i];}else if(f2[x]<f1[j]+w[i])f2[x]=f1[j]+w[i];ans=max(ans,f1[x]+f2[x]);}
}
int main()
{cin>>n>>m;char c;int x,y,z;memset(h,-1,sizeof h);for(int i=1;i<=m;i++){cin>>x>>y>>z>>c;add(x,y,z);add(y,x,z);}dp(1,0);printf("%lld",ans);return 0;
}

这就是基本的树的直径求解的两种方法。

如果有更好的方法,欢迎大家在评论区里留言!


http://chatgpt.dhexx.cn/article/KSXMqvsm.shtml

相关文章

树的直径的概念

树的直径的定义: 在一棵树中&#xff0c;每一条边都有权值&#xff0c;树中的两个点之间的距离&#xff0c;定义为连接两点的路径上边权之和&#xff0c; 那么树上最远的两个点&#xff0c;他们之间的距离&#xff0c;就被称之为&#xff0c;树的直径。 树的直径的别称&#x…

树的直径

【定义】 我们将一棵树T ( V&#xff0c;E )的直径定义为maxδ ( u&#xff0c;v ) ( u&#xff0c;v ∈ V )&#xff0c;也就是说&#xff0c;树中所有最短路径距离的最大值即为树的直径。 【做法】 例题传送门Cow Marathon&#xff08;POJ 1985&#xff09; 对于树的直径…

浅谈树的直径

一、定义&#xff1a; 我们将一棵树T(V,E)的直径定义为max(u,v) (u,v∈V)&#xff0c;也就是说&#xff0c;树中所有最短路径距离的最大值即为树的直径。&#xff08;就是树中的最长路径的长度&#xff09; 二、求解树德直径&#xff1a; 求得树的直径有两种方法&#xff0c;一…

3.网络基础-三层路由网络

3.1、IP地址 初识IP地址 • 在IP网络中&#xff0c;通信节点需要有一个唯一的IP地址&#xff1b; • IP地址用于IP报文的寻址以及标识一个节点&#xff1b; • IPv4地址一共32bits&#xff0c;使用点分十进制的形式表示&#xff1b; IP地址的分类 E类是保留地址 公有IP及私有…

计算机网络——配置动态路由实验

配置动态路由实验 实验目的实验软件实验要求实验知识实验步骤实验结果 实验目的 掌握 RIP 协议配置。RIP 协议配置的命令为&#xff1a;router(config)#network <connected-network> 其中参数 <connected-network> 表示路由器的直连网络号。 实验软件 Cisco Pac…

路由技术基础

路由技术是在网络拓扑结构中为不同节点的数据提供传输路径的技术&#xff0c;路由选择算法是其核心内容。路由选择算法分为静态路由选择算法和动态路由选择算法。 一.路由基础 1.路由的基本概念 路由、路由器 &#xff08;1&#xff09;路由 路由是指导IP报文从源发送到目…

网络路由交换 -- 静态路由 和 缺省路由

1.IP路由基础 1.什么是静态路由&#xff1f; 静态路由是由管理员手工添加的路由条目&#xff1b;通过静态路由添加的都是非直连网段。 2.静态路由的特点&#xff1f; 静态路由的添加和删除都需要手工完成&#xff1b;静态路由无法适应网络的动态变更&#xff0c;即缺乏适应…

cisco packet tracer配置网络路由

广州大学 计算机网络实验 配置网络路由 利用packet tracer搭建如图网络 中间是三个路由器&#xff0c;两边各接一台计算机。 首先先把网络搭建出来 1是路由器&#xff0c;2是终端设备&#xff0c;3是连接设备的线缆。左键点击1或者2或3&#xff0c;区域4就会出现不同的路由器…

路由的几个基本概念-直连路由/网关路由/主机路由/网络路由/动态路由/静态路由/默认路由

1.动态路由/静态路由 1&#xff09;动态路由 路由选择器自动共享路由信息 自动构造路由表&#xff0c;需要一个路由协议&#xff0c;如RIP或OSPF 2&#xff09;静态路由 路由选择器不共享路由信息&#xff08;单方向路由&#xff09; 手工构造路由表 2.直连路由/网关路由…

计算机网络-实验四:配置网络路由

一、实验目的 了解路由器的特点、基本功能及配置方法&#xff1b;使用模拟软件Packet Tracer 8.0&#xff0c;熟悉Cisco路由器的操作&#xff1b;配置静态路由和距离矢量路由协议RIP&#xff0c;实现给定网络的连通&#xff1b;从而加深对IP编址、路由转发机制、路由协议、路由…

广州大学 计算机网络实验 2020版 配置网络路由

一、实验目的 了解路由器的特点、基本功能及配置方法&#xff1b;使用模拟软件 Packet Tracer 5.3 熟悉 Cisco 路由器的操 作&#xff1b;配置静态路由和距离矢量路由协议 RIP&#xff0c;实现给定网络的连通&#xff1b;从而加深对IP 编址、路由转发机制、路由协 议、路由表的…

Ad hoc网络路由协议概述1——分类

目录 1. 传统Internet网络路由协议 1.1 距离矢量路由协议&#xff08;Distance Vector&#xff09; 1.2 链路状态路由协议&#xff08;Link State&#xff09; 1.3 在Ad hoc网络中的不适用性 1.3.1 动态变化的网络拓扑结构 1.3.2 周期性的广播拓扑信息 1.3.3 单向的无线…

3.2 Ad Hoc 网络路由协议

Ad Hoc 网络路由协议 Ad Hoc 网络路由面临的问题 在设计Ad Hoc 网络路由协议时&#xff0c;我们首先要明确可能面临的问题&#xff1a; &#xff08;1&#xff09;路由信息不易获得&#xff1a;定期交换路由信息的开销大、网络资源有限&#xff0c;并且必须被所有节点共享、节…

Ad hoc网络路由协议概述2——表驱动路由协议(1)DSDV协议(Destination-sequenced distance vector protocol)

目录 1 DSDV协议的先导协议: DV协议的困境 2 解决DV协议计数到无穷的困境 2.1 毒性反转 (Poisoned reverse) 2.2 增加序列号 3 DSDV协议 3.1 基本流程 3.2 广播机制 3.2.1 交换路由信息的两个时刻 3.2.2 交换路由信息的两种方式 3.2.3 序列号不同如何选择 3.2.4 序列…

Ad hoc网络路由协议概述4——按需路由协议(2)AODV协议 (Ad-hoc on-demand distance vector algorithm protocol)

目录 1 一点前言 2 路由发现 2.1 相关概念 2.2 AODV的路由发现过程 2.3 与DSDV协议的对比 3 路由表管理及维护 3.1 更新路由表的策略 4 AODV协议的特点 4.1 优点 4.2 缺点 1 一点前言 在之前提过的DSR协议中&#xff0c;采用了源节点路由方式&#xff0c;每个数据报…

计算机网络实验四:配置网络路由

1、相关知识点 1.1 路由器的一般知识&#xff1a; 路由器是局域网与广域网之间进行互联的关键设备。通过它不仅可以互联不同协议、不 同物理接口的网络&#xff0c;还能选择数据传送的路经&#xff0c;并能阻隔非法访问。它在异构网互联能力、 拥塞控制能力和网段的隔离能力等方…

linux 默认路由 主机路由 网络路由

route命令 oute 命令的输出项说明 输出项 说明 Destination目标网段或者主机Gateway网关地址&#xff0c;”*” 表示目标是本主机所属的网络&#xff0c;不需要路由Genmask网络掩码Flags标记。一些可能的标记如下&#xff1a; U — 路由是活动的 H — 目标是一个主机 G — 路…

计算机网络路由转发题

1&#xff09;、目的地址和142.150.64.0/24明显不匹配&#xff0c;所以只有B、C、D&#xff0c;把相应的网络地址算出来 B-网络地址&#xff1a;142.150.71.128 C-网络地址&#xff1a;142.150.71.128 D-网络地址&#xff1a;142.150.0.0&#xff0c;把目的地址逐条的和子网…

各种路由的概念-直连路由、网关路由、主机路由、网络路由等

各种路由的概念 路由的分类 直连路由在添加的时候使用的是出接口&#xff08;dev&#xff09; 网关路由在添加的时候使用的是下一跳&#xff08;gw&#xff09; 主机路由的目的地址是一个完整的主机地址&#xff08;host&#xff09; 网络路由的目的地址是一个网络地址&#…

片上网络路由算法综述

一、 片上网络概述 在半个多世纪以来&#xff0c;半导体工业一直遵循着“摩尔定律”发展&#xff0c;即集成电路上可容纳的晶体管数目&#xff0c;约每隔两年便会增加一倍。截至目前&#xff0c;处理器中的晶体管数量最多已达到了上百亿。晶体管数量的增加一方面极大提升了单核…