树的直径的求法即相关证明【树形DP || DFS】

C++树形结构(2 树的直径) 树的直径 阅读详情

学习大佬:树的直径求法及证明 

树的直径

定义:

一棵树的直径就是这棵树上存在的最长路径。

给定一棵树,树中每条边都有一个权值,树中两点之间的距离定义为连接两点的路径边权之和。树中最远的两个节点之间的距离被称为树的直径,连接这两点的路径被称为树的最长链。后者通常也可称为直径,即直径是一个数值概念,也可代指一条路径。

求法:

一、树形dp

时间复杂度:O( n );

优点:代码量少实现方便。

不足:不容易记录路径。

实现过程:

状态:d[ x ] 以当前结点 x 为根的 子树的直径。

我们枚举每一个结点 x 以及 它要到达的下一个结点 Eiv。

这两个结点所能达到的最大距离之和 加上 这两个结点的边权就有可能去更新树的直径。

即:树的直径 ans_max = max{ d[ x ] + d[ Eiv ] + edge[x, Eiv] } (1 <= x <= N)

那么 d[ x ] 通过什么更新呢?当然是由 它所连接下一个结点所能达到最大距离 来更新了;

即 d[ x ] = max{ d[ x ], d[ Eiv ] + edge[ x, Eiv ] };

核心代码:

 1 void dp(int st)
 2 {
 3     vis[st] = true;             //当前结点已访问
 4     for(int i = head[st]; i != -1; i = edge[i].nxt){
 5         int Eiv = edge[i].v;
 6         if(vis[Eiv]) continue;  //不走回头路
 7         dp(Eiv);
 8         ans_max = max(ans_max, d[st] + d[Eiv] + edge[i].w); //更新树的直径(由当前结点两段之和更新)
 9         d[st] = max(d[st], d[Eiv]+edge[i].w);                    //更新当前结点所能走的最长路径(保留较长的那边)
10     }
11 }

 

二、DFS || BFS 

时间复杂度: O( n );

优点:可以在第一次 dfs/bfs记录前驱

不足:代码量稍大

实现过程:

前提:

两次dfs或bfs。第一次任意选一个点进行dfs(bfs)找到离它最远的点,此点就是最长路的一个端点,再以此点进行dfs(bfs),找到离它最远的点,此点就是最长路的另一个端点,于是就找到了树的直径。

证明(by大佬):

假设此树的最长路径是从s到t,我们选择的点为u。反证法:假设搜到的点是v。
1、v在这条最长路径上,那么dis[u,v]>dis[u,v]+dis[v,s],显然矛盾。
2、v不在这条最长路径上,我们在最长路径上选择一个点为po,则dis[u,v]>dis[u,po]+dis[po,t],那么有dis[s,v]=dis[s,po]+dis[po,u]+dis[u,v]>dis[s,po]+dis[po,t]=dis[s,t],即dis[s,v]>dis[s,t],矛盾。
也许你想说u本身就在最长路径,或则其它的一些情况,但其实都能用类似于上面的反证法来证明的。
综上所述,你两次dfs(bfs)就可以求出最长路径的两个端点和路径长度。

核心代码:

 1 void dfs(int s)
 2 {
 3     for(int i = head[s]; i != -1; i = edge[i].nxt){
 4         int Eiv = edge[i].v;
 5         if(fa[s] == Eiv) continue; //不走回头路,也可以递归父亲结点省去fa数组空间
 6         fa[Eiv] = s;
 7         dis[Eiv] = dis[s] + edge[i].w;  //当前结点最长路径
 8         dfs(Eiv);
 9     }
10 }

 

三、举栗子

1、POJ 1985 Cow Marathon

Cow Marathon

Time Limit: 2000MS Memory Limit: 30000K
Total Submissions: 6925 Accepted: 3279
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 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

Hint

The longest marathon runs from farm 2 via roads 4, 1, 6 and 3 to farm 5 and is of length 20+3+13+9+7=52. 

 

题意概括:

建一颗 N 个节点 M 条边的树,求树上两点最长距离(树的直径);方向都是虚的,建双向边。

解题思路:

①树形dp

AC code:

 1 //树形dp版
 2 #include <cstdio>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cstring>
 6 #include <vector>
 7 #define INF 0x3f3f3f3f
 8 using namespace std;
 9 const int MAXN = 5e4+5;
10 int d[MAXN];
11 bool vis[MAXN];
12 int head[MAXN], cnt;
13 int N, M, ans_max;
14 struct Edge
15 {
16     int v, w, nxt;
17     Edge(int _v = 0, int _w = 0, int _nxt = 0):v(_v), w(_w), nxt(_nxt){};
18 }edge[MAXN<<1];
19 
20 void init()
21 {
22     memset(head, -1, sizeof(head));
23     memset(d, 0, sizeof(d));
24     memset(vis, false, sizeof(vis));
25     cnt = 0;
26 }
27 
28 void AddEdge(int from, int to, int weight)
29 {
30     edge[cnt] = Edge(to, weight, head[from]);
31     head[from] = cnt++;
32 }
33 
34 void dp(int st)
35 {
36     vis[st] = true;             //当前结点已访问
37     for(int i = head[st]; i != -1; i = edge[i].nxt){
38         int Eiv = edge[i].v;
39         if(vis[Eiv]) continue;  //不走回头路
40         dp(Eiv);
41         ans_max = max(ans_max, d[st] + d[Eiv] + edge[i].w); //更新树的直径(由当前结点两段之和更新)
42         d[st] = max(d[st], d[Eiv]+edge[i].w);                    //更新当前结点所能走的最长路径(保留较长的那边)
43     }
44 }
45 
46 int main()
47 {
48     while(~scanf("%d%d", &N, &M))
49     {
50         init();
51         char ccc;
52         for(int i = 1, u, v, w; i <= M; i++){
53             scanf("%d%d%d %c", &u, &v, &w, &ccc);
54             AddEdge(u, v, w);
55             AddEdge(v, u, w);
56         }
57         //printf("%d\n", ans);
58         ans_max = 0;
59         dp(1);
60         printf("%d\n", ans_max);
61     }
62     return 0;
63 }
View Code

②两次DFS

AC code:

 1 //DFS版
 2 /*
 3 #include <cstdio>
 4 #include <iostream>
 5 #include <algorithm>
 6 #include <cstring>
 7 #include <vector>
 8 #define INF 0x3f3f3f3f
 9 using namespace std;
10 const int MAXN = 5e4+5;
11 int dis[MAXN], fa[MAXN];
12 int head[MAXN], cnt;
13 int N, M, ans;
14 
15 struct Edge
16 {
17     int v, w, nxt;
18     Edge(int _v = 0, int _w = 0, int _nxt = 0):v(_v), w(_w), nxt(_nxt){};
19 }edge[MAXN<<1];
20 
21 void AddEdge(int from, int to, int weight)
22 {
23     edge[cnt] = Edge(to, weight, head[from]);
24     head[from] = cnt++;
25 }
26 
27 void init()
28 {
29     memset(head, -1, sizeof(head));
30     for(int i = 0; i <= N; i++) fa[i] = i;
31     cnt = 0;
32     ans = 0;
33 }
34 
35 void dfs(int s)
36 {
37     for(int i = head[s]; i != -1; i = edge[i].nxt){
38         int Eiv = edge[i].v;
39         if(fa[s] == Eiv) continue; //不走回头路,也可以递归父亲结点省去fa数组空间
40         fa[Eiv] = s;
41         dis[Eiv] = dis[s] + edge[i].w;  //当前结点最长路径
42         dfs(Eiv);
43     }
44 }
45 
46 int main()
47 {
48     while(~scanf("%d%d", &N, &M))
49     {
50         init();
51         char ccc;
52         for(int i = 1, u, v, w; i <= M; i++){
53             scanf("%d%d%d %c", &u, &v, &w, &ccc);
54             AddEdge(u, v, w);
55             AddEdge(v, u, w);
56         }
57         //printf("%d\n", ans);
58         int ans_max = 0, ans_index = 0;
59         dfs(1);                         //第一次dfs找出树的直径所在的点
60         for(int i = 1; i <= N; i++){
61             if(dis[i] > ans_max){
62                 ans_max = dis[i];
63                 ans_index = i;
64             }
65             dis[i] = 0;
66             fa[i] = i;
67         }
68 
69         dfs(ans_index);                 //第二次dfs找出树的直径
70         for(int i = 1; i <= N; i++){
71             if(dis[i] > ans_max) ans_max = dis[i];
72         }
73         printf("%d\n", ans_max);
74     }
75     return 0;
76 }
View Code

 

 

 

2、POJ 3310 Caterpillar

Caterpillar

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 2505 Accepted: 1180

Description

An undirected graph is called a caterpillar if it is connected, has no cycles, and there is a path in the graph where every node is either on this path or a neighbor of a node on the path. This path is called the spine of the caterpillar and the spine may not be unique. You are simply going to check graphs to see if they are caterpillars.

For example, the left graph below is not a caterpillar, but the right graph is. One possible spine is
shown by dots.

 

 

Input

There will be multiple test cases. Each test case starts with a line containing n indicating the number of nodes, numbered 1 through n (a value of n = 0 indicates end-of-input). The next line will contain an integer e indicating the number of edges. Starting on the following line will be e pairs n1 n2 indicating an undirected edge between nodes n1 and n1. This information may span multiple lines. You may assume that n ≤ 100 and e ≤ 300. Do not assume that the graphs in the test cases are connected or acyclic.

Output

For each test case generate one line of output. This line should either be

     Graph  g  is a caterpillar.
or
     Graph  g  is not a caterpillar.

as appropriate, where g is the number of the graph, starting at 1.

Sample Input

22
21
1 2 2 3 2 4 2 5 2 6 6 7 6 10 10 8 9 10 10 12 11 12 12 13 12 17
18 17 15 17 15 14 16 15 17 20 20 21 20 22 20 19
16
15
1 2 2 3 5 2 4 2 2 6 6 7 6 8 6 9 9 10 10 12 10 11 10 14 10 13 13 16 13 15
0

Sample Output

Graph 1 is not a caterpillar.
Graph 2 is a caterpillar.

 

 

题意概括:

首先需要判断给的图是不是一棵树;

其次需要判断是否存在一条路径使得图上所有的点要么在这条路径上,要么距离该路径的距离为 1。

解题思路:

判断是否为一棵树直接dfs判断是否存在环即可;

为了让最多的点满足第二个条件,则这条路径一定是树的直径。

两次DFS求出树的直径,遍历一遍判断是否所有点都满足条件。

为了做这个判断,DFS时不仅要更新树的直径还要同时更新每一个结点能达到的最长路径;

如果当前结点能达到的最长路径等于树的直径说明该结点在树的直径上,如果不能则判断他是否能通过相连的结点到达树的直径。

 

AC code:

 1 #include <bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 using namespace std;
 4 const int MAXN = 300;
 5 struct Edge{int v; int nxt;}edge[MAXN<<1];
 6 int head[MAXN], cnt;
 7 int dis[MAXN], bb[MAXN];
 8 bool vis[MAXN];
 9 int N, M;
10 int ans_max, ans_index;
11 bool chck;
12 
13 void init()
14 {
15     memset(head, -1, sizeof(head));
16     memset(vis, false, sizeof(vis));
17     memset(dis, 0, sizeof(dis));
18     memset(bb, 0, sizeof(bb));
19     cnt = 0;
20     chck = false;
21     ans_max = 0; ans_index = 0;
22 }
23 
24 void AddEdge(int from, int to)
25 {
26     edge[cnt].v = to;
27     edge[cnt]. nxt = head[from];
28     head[from] = cnt++;
29 }
30 
31 void check(int s, int fa)
32 {
33     vis[s] = true;
34     for(int i = head[s]; i != -1; i = edge[i].nxt){
35         int Eiv = edge[i].v;
36         if(Eiv == fa) continue;
37         if(vis[Eiv]) {chck = true; return;}
38         check(Eiv, s);
39         if(chck) return;
40     }
41 }
42 
43 void dfs(int s, int fa)
44 {
45     for(int i = head[s]; i != -1; i = edge[i].nxt){
46         int Eiv = edge[i].v;
47         if(Eiv != fa){
48             dis[Eiv] = dis[s] + 1;
49             bb[Eiv] = dis[Eiv];
50             if(dis[Eiv] > ans_max) {ans_max = dis[Eiv]; ans_index = Eiv;} //更新树的直径
51             dfs(Eiv, s);
52             bb[s] = max(bb[s], bb[Eiv]);            //更新当前结点最长路径
53         }
54     }
55 }
56 
57 int main()
58 {
59     int T_case = 0;
60     while(~scanf("%d", &N) && N){
61         scanf("%d", &M);
62         init();
63         for(int m = 1, u, v; m <= M; m++){
64             scanf("%d%d", &u, &v);
65             AddEdge(u, v);
66             AddEdge(v, u);
67         }
68 
69         if(M > N-1) chck = true;
70         if(!chck) check(1, 0);                          //判断是否存在环
71         if(!chck){
72             for(int i = 1; i <= N; i++){
73                 if(!vis[i]){chck = true; break;}        //判断所有点是否联通
74             }
75             if(!chck){
76                 dis[1] = 0;
77                 dfs(1, 0);                              //第一次dfs找出树的直径所在的点
78                 dis[ans_index] = 0;
79                 dfs(ans_index, 0);                      //第二次dfs找出树的直径
80                 for(int i = 1; i <= N; i++){            //判断所有的点是否满足条件
81                     bool flag = false;
82                     if(bb[i] == ans_max) continue;                 //在直径上
83                     for(int k = head[i]; k != -1; k = edge[k].nxt){         //判断不在树的直径上的点到树的直径距离是否为 1
84                         if(bb[edge[k].v] == ans_max) {flag = true; break;}
85                     }
86                     if(!flag) {chck = true; break;}
87                 }
88             }
89         }
90         if(chck) printf("Graph %d is not a caterpillar.\n", ++T_case);
91         else printf("Graph %d is a caterpillar.\n", ++T_case);
92     }
93     return 0;
94 }
View Code

 

算法学习——树形DP——多叉树的最长路径 这个树形DP算是全部总结完毕了,下次谁再来问我,说树形DP是什么,我狠狠打打他的脸! 阅读详情

相关推荐

基于Xilinx的I2S Receiver IP核和I2S Transmitter IP核音频验证

基于Xilinx的I2S Receiver IP核和I2S Transmitter IP核音频验证 文章目录前言一、工程构架二、Xilinx IP的配置1.I2S Transmitter IP配置:2.I2S Receiver IP配置:3.WM8960的配置:总结 前言 本实验基于Xilinx ZU4EV平台,也适用于ZYNQ平台。音频验证完成,记录调过程。 ①Xilinx 音频IP只支持主模式,左对齐或右对齐方式,16bit或24bit字长。 ②WM8960器件作为从模式;24bit字长;数据传输格

weixin_45637597的博客 6815

树的直径详解

树的直径,又称树的最长链,定义为一棵树上最远的两个节点的路径,即树上一条不重复经过某一条边的最长的路径。树的直径也可以代指这条路径的长度。 求树的直径有两种比较常用的方法:树形DP和搜索,时间复杂度均为$O(n)$。接下来会对两种方法都进行讲解。 在接下来的实现中,树是以邻接表存无向边的形式给出的。 树形DP 设$d_x$表示从$x$走向以其为根的子树,能够到达的最远距离。再...

6239

国产麒麟系统下用Rider开发C#桌面应用:从环境配置到Avalonia UI实战

本文详细介绍了在国产麒麟系统上使用JetBrains Rider开发C#桌面应用的完整流程,重点讲解了Avalonia UI框架的实战应用。从环境配置、Rider安装到Avalonia项目创建和UI开发技巧,全面覆盖了在非Windows环境下进行C#开发的关键步骤和优化建议,助力开发者高效构建跨平台桌面应用。

weixin_27791839的博客 387

【算法专题】树的直径

树的直径 定义:树中距离最远的两个点之间的距离被称为树的直径。 1 做法 做法一 (1)任取一点作为起点x,找到距离该点最远的一个点y; (2)再找到距离y最远的一点z,那么y、z之间的路径就是一条直径。 证明:核心是证明y一定是直径的一个端点。使用反证法证明,存在如下两种情况。 假设y不是直径的一个端点。假设uv是直径。 对于情况一:因为y是距离x最远的一个点,因此有ya + ax >= ua + ax,所以ya >= ua,所以yv >= uv,因此yv才是

weixin_42638946的博客 2533

统信UOS/麒麟Kylin OS下利用pyenv实现Python多版本开发环境搭建指南

本文详细介绍了在统信UOS和麒麟Kylin OS国产操作系统下使用pyenv搭建Python多版本开发环境的完整指南。从系统环境准备、pyenv定制安装到Python版本编译实战,提供了针对国产CPU架构的特殊优化方案和常见问题解决方法,帮助开发者高效管理不同Python版本需求。

sea99的博客 1053

汽车UDS诊断之诊断会话控制服务(0x10)深度剖析

DiagnosticSessionControl就是诊断会话控制。 请求消息定义 A_Data类型 参数名称 Cvt 字节值 助记符 #1 诊断会话控制请求SID M 0x10 DSC #2 子功能=[诊断会话类型] M 0x00-0xFF LEV_DS_ ...

心骗小白话的博客 7420

树的直径——定义与求解方法

快速了解树的直径的定义与求解方法。

BasketballChick的博客 4902

Python从0到100完整学习指南(必看导航)

想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Python爬虫、Web开发、 计算机视觉、机器学习、神经网络以及人工智能相关知识,成为学业升学和工作就业的先行者!

拥有百余位万粉技术博主、200余位可合作代发博主,私域技术社群规模达千人,商务合作私信 6万+

树的直径两种求法

首先先介绍一下什么是树的直径,树的直径就是树中所有最短路经距离的最大值。 求树的直径通常有两种方法,一种是通过两次搜索(bfs和dfs均可),另一种就是通过树形dp来求了。 先来介绍一下用两次深搜来求树的直径: 先从图上任意一点,搜索整棵树,找到距离该点最远的点,再用距离该点最远的点搜索一次,即可得到树的直径。 证明我就不写了,给出一位大佬的博客地址,里面有很详细的证明 https://zhuanlan.zhihu.com/p/115966044?from_voters_page=true

AC__dream的博客 6974

从0开始图形学(光栅化)

从0开始图形学

A112459的专栏 2396

YOLO环境配置+项目启动全流程(Conda+PyCharm超详解)

YOLO(You Only Look Once)是一个基于深度学习的目标检测算法,广泛应用于智能识别领域。本篇保姆级教学将手把手教你如何从零开始运行一个YOLO项目,适合完全没有基础的新手。

一键难忘的博客 1541

树的直径解释

树上任意两点之间的最长简单路径即为「树的直径」。

ATION001的博客 2226

【PostgreSQL】PostgreSQL数据库函数比对模板(PG通用)

LOOKUP 函数从单行或单列区域 (区域:工作表上的两个或多个单元格。区域中的单元格可以相邻或不相邻。)或数组 (数组:用于建立可生成多个结果或可对在行和列中排列的一组参数进行运算的单个公式。数组区域共用一个公式;数组常量是用作参数的一组常量。LOOKUP 函数具有两种语法形式:向量形式和数组形式。vlookup查找匹配值超过255个字符显示#Value的解决办法。如果值为错误值 #N/A,则返回 TRUE。

tttzzzqqq2018的博客 1494

树的直径——详解

树上任意两节点之间最长的简单路径即为树的「直径」。前置知识:树基础。显然,一棵树可以有多条直径,他们的长度相等。可以用两次DFS或者树形DP的方法在时间求出树的直径。SPOJPT07Z,Longestpathinatree给定一棵个节点的树,求其直径的长度。。首先从任意节点开始进行第一次DFS,到达距离其最远的节点,记为,然后再从开始做第二次DFS,到达距离最远的节点,记为,则即为树的直径。显然,如果第一次DFS到达的节点是直径的一端,那么第二次

w_w_wwwww的博客 1436

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

算法提高——树上DP(树的直径)

树的直径是图论里边非常高的考察点并且是入门树形dp的基础,竞赛的同学务必重视。树上最远两点(叶子结点)的距离。大臣的旅费 很久以前,T王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。J是T国重要大臣,他巡查于各大城市之间,体察民情。所以,从一个城市马不停蹄地到另一个城市成了J最常做的

leoyongyuan的博客 2445

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

树的直径 两次dfs(起点到其余各点最大距离)、树形dp(各点到其子树叶子节点的最大距离)

树的直径定义法一、两次dfs、bfs思想证明优点缺点实现代码法二、树形dp思想证明优点缺点实现代码题目集参考 定义 直径 : 在圆上两点(不相交)之间最远的距离就是我们通常所说的直径。 树的直径 : 树上最远的两个节点之间的距离就被称为树的直径,连接这两点的路径被称为树的最长链 (一开始,下意识地以为是,找到某个节点到它子树中叶子节点的最大距离,显然不是) 法一、两次dfs、bfs 思想 先从任意一点P出发,找离它最远的点Q,再从点Q出发,找离它最远的点W,W到Q的距离就是是的直径。 证明 ①若P已经在

qq_51070956的博客 1351

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

树的直径&基环树&单调队列

树的直径 定义:树中最远的两个节点之间的距离被称为树的直径。 怎么求呢?有两种官方的算法(不要问官方指谁我也不晓得): 1.两次搜索。首先任选一个点,从它开始搜索,找到离它最远的节点x。然后从x开始搜索,找到离x最远的点y,那 么E(x, y)的长度就是树的直径。时间复杂度为O(n)。 2.树形dp。这种其实更好写。我们可以对于某个节点x,分别求出经过它的最长链的长度。怎么求呢?首先,枚举x...

修电缆的建筑工的博客 1132

浅谈图论中树及其相关知识点(树的遍历、直径、最近公共祖先)(c++)

树的直径是指树中最长的一条简单路径一棵树可以有多条直径可以用DFS或者树形DP在On时间内求出一棵树的直径对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u和v的祖先且x的深度尽可能大。在这里,一个节点也可以是它自己的祖先。

2301_79587247的博客 1364

poj1985 Cow Marathon(树的直径)

Cow Marathon Time Limit:2000MS Memory Limit:30000K Total Submissions:9653 Accepted:4411 Case Time Limit:1000MS Description After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to get more exercise, ...

。 535

专题 树上问题之树的直径&好题精析

我们将一棵树的直径定义为,也就是说,树中所有最短路径距离的最大值即为树的直径。为什么树的定义类似于图?的形式)什么是树上最短路径的最大值?如何去求解?以下笔者将一一回答。主要还是学习一下树的直径一些性质,并学习一下惯用的套路,这几道题基本都很具有代表性。

2503_92193114的博客 960

树的直径

【定义】 这棵树中距离最远的两个结点之间相隔的距离。注意:是任意两个结点的最远距离,不是树的深度,显然,树的直径可以有很多条。 【两次dfs或者(两次bfs)】 思想:先从任意一点P出发,找离它最远的点Q,再从点Q出发,找离它最远的点W,W到Q的距离就是是的直径 证明如下(来自:https://blog.youkuaiyun.com/forever_dreams/article/detai...

pxlsdz的博客 466

【总结】树形dp

树形dp总结

and 435

【算法】Tree Diameter 树的直径

方法很简单,找一个节点A,从A出发到距离A最远的节点B,然后从节点B出发,找到距离节点B最远的节点C。然后B~C就是这个树中最远的距离,也称为树的直径,即这个路径上边的数量。同时为了记录u的最长的2个路径,定义d1[n],d2[n] 分别表示从 u出发的最长路径d1[u],和 次长路径d2[u].简单来说,分为2步,每一步都是找距离当前节点最远的一个节点。当节点 v 的处于最长的路径上,这个最长的路径L 可能的组成就有几个情况。2 V 在路径上,并且 从V向下的最长路径,一定是这个L的组成部分。

Cui's Blog 792

树论相关

树的直径 定义:对于一颗无根树,找到两个点,使得他们之间的距离最远,这个距离就是树的直径。 求法: 两次bfs或dfs(O(n)):第一次以任意节点 x 为根,求出距离最远点 y,这个点一定在树的直径上(证明:树的直径求法及证明),第二次以这个点为根跑出来的最远点 z,y 与 z 的距离,就是树的直径。 树形 dp(O(n)) :dp[ i ]表示经过 i 点的最长链长度。 性质: 直径两端...

C'est la vie! 408
上一篇: HDU 3038 How Many Answers Are Wrong 【YY && 带权并查集】
下一篇: POJ 1984 Navigation Nightmare 【经典带权并查集】
莜莫oO
博客等级 码龄9年 7粉丝 226原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值