树形结构 —— 树与二叉树 —— 树的直径
【定义】
给定一棵树,树中的每条边都有一个权值。
- 树中两点的距离:连接两点的路径边权之和
- 树的直径:树中最远的两个节点之间的距离
- 树的最长链:连接树中最远的两个结点的路径
【实现】
树的直径通常有两种求法,时间复杂度均为O(n)。
假设树以 n 个点 n-1 条边的无向图形式给出,存储在邻接表中。
1.两次DFS求树的直径
通过两次 dfs 可以求树的直径,且更容易计算出直径上的具体结点
- 从任意结点出发,通过 dfs 对树进行一次遍历,求出于出发点距离最远的结点,记为 st
- 从结点 st 出发,通过 dfs 对树再进行一次遍历,求出于 st 距离最远的结点,记为 ed
则:st 到 ed 的路径就是树的直径
在第 2 步的遍历中,可以记录下来每个点第一次被访问的前驱节点,最后从 q 递归到 p,即可得到直径的具体方案
struct Edge {int to, val;int next;Edge(){}Edge(int to,int val,int next):to(to),val(val),next(next){}
} edge[N];
int n;
int head[N], tot;
int dis[N], maxx, id;
int st, ed, diameter;//起点、终点、直径
int disSt[N], disEd[N];//起点、终点分别到每个点的距离
void addEdge(int from, int to, int val) {edge[++tot].to = to;edge[tot].val = val;edge[tot].next = head[from];head[from] = tot;
}
void dfs(int x, int father) {for (int i = head[x]; i != -1; i = edge[i].next) {int y = edge[i].to;int val = edge[i].val;if (y == father)continue;dis[y] = dis[x] + val;if(dis[y]>maxx){maxx = dis[y];id = y;}dfs(y, x);}
}
void calcDiameter(){//第一遍dfsmaxx = 0;id = 1;dfs(1, 0);st = id;//第二遍dfsmaxx = 0;dis[st] = 0;dfs(st, 0);ed = id;diameter = maxx; //树的直径for (int i = 1; i <= n; i++)disSt[i] = dis[i];dis[ed] = 0;dfs(ed, 0);for (int i = 1; i <= n; i++)disEd[i] = dis[i];
}int main() {scanf("%d", &n);memset(head, -1, sizeof(head));for (int i = 1; i <= n - 1; i++) {int x, y, val;scanf("%d%d%d", &x, &y, &val);addEdge(x, y, val);addEdge(y, x, val);}calcDiameter();printf("%d %d\n", st, ed);printf("%d\n", diameter);return 0;
}
2.树形DP求树的直径
设 1 号节点为根,n 个点 n-1 条边的无向图就可以看做有根树
设 dis1[x] 表示从点 x 到以 x 为根的子树中叶结点的最长链, pos1[x] 表示 dis1[x] 在哪个点更新;dis2[x] 表示从点 x 到以 x 为根的子树中叶结点的次长链,pos2[x] 表示 dis2[x] 在哪个点更新,且要求两条链不能有交集。
这样一来,对于任意一点 i,经过点 i 的最长链的分为两个部分:i 的最长链 dis1[i]、i 的次长链 dis2[i]
那么,整棵树的直径就是
struct Edge {int to, val;int next;Edge(){}Edge(int to,int val,int next):to(to),val(val),next(next){}
} edge[N];
int n;
int head[N], tot;
int dis1[N], dis2[N];//分别维护第i个点的最长链、次长链
int pos1[N],pos2[N];//分别维护dis1[i]、dis2[i]从哪个点更新
void addEdge(int from, int to, int val) {edge[++tot].to = to;edge[tot].val = val;edge[tot].next = head[from];head[from] = tot;
}
void dfs(int x, int father) {for (int i = head[x]; i != -1; i = edge[i].next) {int y = edge[i].to;int val = edge[i].val;if (y == father)continue;dfs(y, x);if (dis1[y] + val > dis1[x]) {dis2[x] = dis1[x];dis1[x] = dis1[y] + val;pos2[x] = pos1[x];pos1[x] = y;} else if (dis1[y] + val > dis2[x]) {dis2[x] = dis1[y] + val;pos2[x] = y;}}
}
int main() {scanf("%d", &n);memset(head, -1, sizeof(head));for (int i = 1; i <= n - 1; i++) {int x, y, val;scanf("%d%d%d", &x, &y, &val);addEdge(x, y, val);addEdge(y, x, val);}dfs(1, 0);int diameter = -INF;for (int i = 1; i <= n; i++)diameter = max(dis1[i] + dis2[i], diameter);printf("%d", diameter);return 0;
}
树形结构 —— 树与二叉树 —— 树的直径相关推荐
- 6.4 树和二叉树-树和森林
树和二叉树-树和森林 1. 树和森林的表示方法 1.1 树的三种存储结构-`双亲`表示法 1.2 树的三种存储结构-`孩子链表`表示法 1.3 树的三种存储结构-`孩子兄弟(二叉链表)(二叉树)`表示 ...
- PHP算法 《树形结构》 之 伸展树(1) - 基本概念
伸展树的介绍 1.出处:http://dongxicheng.org/structure/splay-tree/ A. 概述 二叉查找树(Binary Search Tree,也叫二叉排序树,即Bin ...
- 数据库树形结构,EasyUI Tree 树
通过 $.fn.tree.defaults 重写默认的 defaults. 树(tree)在网页中以树形结构显示分层数据.它向用户提供展开.折叠.拖拽.编辑和异步加载功能. 树的数据格式(Tree D ...
- 树形结构 —— 树与二叉树 —— 树的中心
[概述] 树的中心问题是指:当给出 n 个结点与 n-1 条边后,要选定一个点作为整棵树的根结点,使得从该点到每个叶结点的最长路径最短. 树的中心问题主要有两种方法:DFS/BFS 进行搜索.树形 D ...
- 树形结构 —— 树与二叉树 —— 树的重心
[概述] 树的重心也叫树的质心,对于一棵具有 n 个结点的无根树,找到一个点,使得将树变为以该点为根的有根树时,最大子树的结点数最小. 简单来说,就是给定一棵 n 个点的树,当删除某点 x 后,使得最 ...
- 树形结构 —— 树与二叉树 —— 树的数据生成器
为方便测试数据,给出一个树的数据生成器. 树的结点为 1~10 个,边权为 1~100,各点编号随机化 struct Edge {int x, y;int dis; } edge[N]; int n, ...
- 树形结构 —— 树与二叉树
[概述] 树是一种非线性的.递归定义的有序数据结构,能很好地描述有分支和层次特性的数据集合. 二叉树是树的一种形态,是 n 个结点的有限集合,该集合或为空集(空二叉树),或由一个根结点与两棵互不相交的 ...
- 数据结构--树和二叉树
文章目录 树和二叉树 树 1.树的定义 2.树的逻辑表示 3.树的基本术语: 4.树的性质 5.树的基本运算 二叉树 二叉树的存储结构 二叉树的遍历 树和二叉树 树 1.树的定义 2.树的逻辑表示 树 ...
- 数据结构与算法——树和二叉树***
第五章 :树和二叉树 树和图是两种重要的非线性结构.线性结构中结点具有唯一前驱和唯一后继的关系,而非线性结构中结点之间的关系不再具有这种唯一性.其中,树形结构中结点间的关系是前驱唯一而后继不唯一,即元 ...
最新文章
- pandas重置dataframe的索引(reset_index)、如果索引不匹配dataframe操作时候的问题、重置索引(不设置drop=true)远索引生成新的数据列
- 学号 20172326 《程序设计与数据结构》第三周学习总结
- 饱和气压与温度的关系_凯米斯小课堂 | 溶解氧与水产养殖的关系
- JVM垃圾回收的时候如何确定垃圾?什么是GC Roots?
- Class对象和Java反射机制
- 绵阳python培训_《绵》字意思读音、组词解释及笔画数 - 新华字典 - 911查询
- 中南林业科技大学的计算机研究生分数线,2019中南林业科技大学研究生分数线汇总(含2016-2019历年复试)...
- WSDL文件生成WEB service server端C#程序
- 秒懂系列 | 史上最简单的Python Django入门教程
- Markdown标题、行首缩进、换行。csdn(1)
- angularJs的spa页面切换以及ngRoute模块
- await和async
- java下载m3u8视频,解密并合并ts(一)
- 健康管理师考试重点详解!(基础知识篇)
- Vulkan编程指南翻译 第六章 着色器和管线 第2节 SPIR-V 概述
- mysql中的comment_请问一下在mysql中的 COMMENT 有什么作用吗??
- Laya Tween循环
- 荣耀Magic 3Pro 充电架构分析
- 你应该掌握的浏览器相关知识
- 英才计划计算机潜质测评试题,2018年“英才计划”综合实践活动通知