树的直径求法与性质(附例题)

  树的直径指树上距离最远的两点间的距离,它在树上问题上有许多应用,往往通过树的直径的性质可以将一个高时间复杂度的解法变为线性求解。对于树上两点间距离通常有三种定义,我们根据这三种情况分别讨论一下它的性质

树的直径的求法:

树的直径有两种求法,时间复杂度都是O(n)

①贪心求法:

贪心求直径的方法是任意找一个点为根,dfs整棵树找到距离他最远的点xx,再以这个点x为根求出距离它最远的点y,(x,y)即为直径

②DP求法:

DP求直径的方法是对于每个点记录这个点子树中的最长链及与最长链处于不同子树中的次长链,用每个点的最长链+次长链更新直径,然后再将最长链上传到父节点更新父节点的最长链或次长链

这种求法适用于所有求树的直径的情况

一、

定义两点间距离为两点间路径上的边权和,边权非负。

贪心求直径的方法适用于这种树的直径。

证明:

假设确定了直径的一个端点,那么另一个端点一定是距离这个端点最远的点,所以第二次找最远点的贪心一定正确

我们采用反证法,假设第一次从a开始找,找到的点是x而存在一个点u使得以u为根找最远点v形成的直径要比以x为根找最远点形成的直径长。假设两点间距离用dis表示

如果(x,u)的路径与(u,v)的路径不相交,dis(x,u)+dis(u,v)一定比dis(u,v)长,假设不成立

如果(x,u)的路径与(u,v)的路径相交,假设两路径的另一交点为yy,那么dis(x,y)>dis(u,y)),因为以a为根时x的深度比u的深度深,所以手画一下就能看出来

性质:

1、直径两端点一定是两个叶子节点

2、距离任意点最远的点一定是直径的一个端点,这个基于贪心求直径方法的正确性可以得出

3、对于两棵树,如果第一棵树直径两端点为(u,v),第二棵树直径两端点为(x,y),用一条边将两棵树连接,那么新树的直径一定是u,v,x,y中的两个点

证明:如果新树直径不是原来两棵树中一棵的直径,那么新直径一定经过两棵树的连接边,新直径在原来每棵树中的部分一定是距离连接点最远的点,即一定是原树直径的一个端点。

4、对于一棵树,如果在一个点的上接一个叶子节点,那么最多会改变直径的一个端点

证明:假设在xx下面接一个点yy,直径变成了(u,x),原树直径为(a,b),那么dis(u,x)>dis(a,b),dis(u,x)=dis(u,y)+1,

即dis(u,y)+1>dis(a,b),如果dis(u,y)<dis(a,b),那么显然不成立;

如果dis(u,y)=dis(a,b),那么(u,y)也是原树的直径,符合上述结论。

5、若一棵树存在多条直径,那么这些直径交于一点且交点是这些直径的中点

二、

定义树的直径为两点间路径上边权和+两点点权和,点权可以为负数,边权非负。

这种情况满足贪心求法及上述2、3性质,同样证明一下贪心求法及性质2:

可以发现性质二满足的原因是贪心求法的成立,所以只需要证明贪心的成立即可。

假设第一次dfs以a为根,深度+点权的最大点为x,假设存在一个更优点u使得从u开始找最远点y形成的直径比从x找最远点形成的直径长

令x与u到根的路径不交集部分长度分别为l(x),l(u),两点点权分别为v(x),v(u),那么l(x)+v(x)>l(u)+v(u)

如果(u,y)与(x,u)不相交,那么显然v(x)+l(x)+l(u)>v(u),dis(x,u)+dis(u,y)+v(x)+v(y)>dis(u,y)+v(u)+v(y)

如果(u,y)与(x,u)相交,假设两路径交点为b,那么也可以得出dis(b,x)+v(x)>dis(b,u)+v(u)的结论

三、

定义树的直径为两点间路径上边权和,边权有负数。

这种情况无法用贪心方法求直径,并且不具备以上性质。

例题:

1.2020杭州学军中学趣味赛B-齐心抗疫

题意:

给定一棵树,找出两个点 x , y 设 dis(x,y) 表示 x 与 y 之间的距离,最大化max(ax , ay) * dis(x , y)

思路:

由于max(ax , ay) * dis(x , y) = max(ax * dis(x,y), ay* dis(x,y)),所以问题等价为求ax* max(dis(x , y ))

于是我们只需要计算出距离每一个点最远的点有多远即可。

设树的直径两端点分别为u 与 v

那么 u 或 v 必然距离点 x 最远。所以我们只需要求出直径后从直径两端点分别

求出每个点到直径两端点距离值即可

2.Codeforces Round#615(Div.3)F - Three Paths on a Tree

题意:

给一棵树,找到三个顶点,使三个顶点两两之间路径的并集最大

思路:

必定会有一组最优解,使得 a,b是树直径上的端点。

证明:

假设某个答案取连接点x。x最远的树到达的点是s,根据树的直径算法,s是树的某个直径a的端点。假设x的最远和第二远的点组成的链是b,b就会和a有一段公共部分。我们取a和b相交部分距离s最远的那个点y。那么取这个链上点y的答案一定比x更优

用两次BFS可以求出直径的两个端点,在这个过程中还能顺便求出一个端点到树上每一点的距离。之后再用一次BFS求得另一个端点到树上每一点的距离。

再枚举第三个顶点c就可以求出这三个顶点了

最终距离为:[dis(a,b)+dis(b,c)+dis(a,c)]/2

原文地址:https://www.cnblogs.com/overrate-wsj/p/12639907.html

时间: 2024-08-28 08:34:05

树的直径求法与性质(附例题)的相关文章

hdu4612 无向图中任意添加一条边后使桥的数量最少 / 无向图缩点+求树的直径

题意如上,含有重边(重边的话,俩个点就可以构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选任意起点U,进行bfs,到达最远的一个点v(level最深)该点必然是树的直径的一个端点,,再从该点出发,bfs,到最深的一点,该点深度就是直径.(证明:先假设u,是直径上一点,S,T是直径的端点,设v!=t,则有(V,U)+(U,S)>(T,U)+(U,S),矛盾,故t=v:若u不是直径上一点,设u到直径上的一点为x,同理易证. 最后 缩

poj1985&amp;&amp;第四次CCF软件认证第4题 求树的直径

Cow Marathon Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 4216   Accepted: 2137 Case Time Limit: 1000MS Description After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to get more exercise, so he has com

hdu4612 无向图中随意加入一条边后使桥的数量最少 / 无向图缩点+求树的直径

题意如上,含有重边(重边的话,俩个点就能够构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选随意起点U,进行bfs,到达最远的一个点v(level最深)该点必定是树的直径的一个端点,,再从该点出发,bfs,到最深的一点.该点深度就是直径. (证明:先如果u.是直径上一点,S,T是直径的端点.设v!=t,则有(V,U)+(U,S)>(T,U)+(U,S),矛盾,故t=v:若u不是直径上一点.设u到直径上的一点为x.同理易证. 最后

算法笔记--树的直径模板

思路: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c之间的距离就是树的直径. 模板: const int N=1e6+5; int head[N]; int dis[N]; bool vis[N]; int cnt=0,b,mxn=0; struct edge { int to,w,next; }edge[N]; void add_edge(int u,

树的直径poj1985

树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c之间的距离就是树的直径. 用dfs也可以. http://poj.org/problem?id=1985 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #inc

&lt;学习笔记&gt; 树的直径 Bfs、Dfs

树的直径为树上最长的一条路径(不经过重复节点),也可以看做是树上最长路. 通常的求法: 1.两边Bfs或两边Dfs 2.树形dp(端点为根和仅经过根). emmm ..蒟蒻表示目前只会第一种QAQ. 从树中找出任意一点,求出与他距离最远的点s,再用同样的方法求出与s距离最远的点t,s-t即为树的直径. Bfs代码 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cma

树的直径方法总结

定义: 直径 : 在圆上两点(不相交)之间最远的距离就是我们通常所说的直径. 树的直径 : 树上最远的两个节点之间的距离就被称为树的直径,连接这两点的路径被称为树的最长链. 求法: 1.树形 DP 2.两次 BFS 或者 两次 DFS 算法 1 : 树形 DP 优点 : 可以有效处理 负边权 缺点 : 对于记录路径的信息效率较低 简单分析 : 先通过递归的方式到叶子底部,然后通过自底向上的方式进行更新距离,找到最长路径. (看下图,可以得到这棵树的直径是经过根节点 1 的 路径最长的链 5 ->

树的直径

*总结的别人博客 树的直径(Diameter)是指树上的最长简单路.直径的求法:两遍BFS (or DFS)任选一点u为起点,对树进行BFS遍历,找出离u最远的点v以v为起点,再进行BFS遍历,找出离v最远的点w.则v到w的路径长度即为树的直径*简单证明于是原问题可以在O(E)时间内求出 关键在于证明第一次遍历的正确性,也就是对于任意点u,距离它最远的点v一定是最长路的一端.如果u在最长路上,那么v一定是最长路的一端.可以用反证法:假设v不是最长路的一端,则存在另一点v’使得(u→v’)是最长路

hdu 4679 树的直径

1 /* 2 题目大意:给n个点n-1条边的树,求删除哪条边时两个树中最大的直径与边权的乘积最小. 3 树的直径(Diameter)是指树上的最长简单路. 4 直径的求法:两遍BFS (or DFS) 5 若删除的边不是直径上的那么花费为max_len*wi 6 若删除的边是直径上的那么花费为max(dp[u][2],dp[v][2])*wi 7 */ 8 #pragma comment(linker, "/STACK:16777216") 9 #include <iostrea