蓝桥备赛指南(14):树的直径与重心

树的直径

什么是树的直径?树的直径是树上最长的一条链,当然这条链并不唯一,所以一棵树可能有多条直径。直径由两个顶点u、v来决定,若由一条直径(u,v),则满足一下性质:

1)u、v的度数均为1;

2)在任意一个点为根的树上,u、v必然存在一个点作为最深的叶子节点。深度就是点距离根节点的距离。

如图所示:

树的直径有两种求法:第一种就是"跑两遍dfs";第二种就是树形dp。

由于直径端点u、v必然存在一个是深度最深的点,那么我们可以在以任意节点为根地树上跑一次dfs求所有点的深度,选取深度最大的点(可能有多个,任取一个)就是v。

于是就可以得到两个端点u、v,从而确定树的直径,其长度就是路径上点的个数,也就等于以u为根的树中的depv

习题:1.卖树 - 蓝桥云课

代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

using ll = long long;
const int N = 1e5 + 9;
vector<int>g[N];

int dep1[N], depu[N], depv[N];

void dfs(int x, int fa, int dep[]) {
	dep[x] = dep[fa] + 1;
	for (const auto& y : g[x]) {
		if (y == fa)continue;
		dfs(y, x, dep);
	}
}

void solve() {
	ll n, k, c; cin >> n >> k >> c;
	for (int i = 1; i < n; ++i) {
		int u, v; cin >> u >> v;
		g[u].push_back(v), g[v].push_back(u);
	}
	dep1[0] = depu[0] = depv[0] = -1;
	dfs(1, 0, dep1);
	int u = 1;
	for (int i = 1; i <= n; ++i) if (dep1[i] > dep1[u]) u = 1;
	dfs(u, 0, depu);
	int v = 1;
	for (int i = 1; i <= n; ++i) if (depu[i] > depu[v])v = i;
	dfs(v, 0, depv);

	ll ans = 0;
	for (int i = 1; i <= n; ++i) {
		ans = max(ans, max(depu[i], depv[i]) * k - dep1[i] * c);
	}
	cout << ans << endl;
	for (int i = 1; i <= n; ++i) g[i].clear();
}

int main() {
	int t; cin >> t;
	while (t--) {
		solve();
	}
	return 0;
}

树的重心

树的重心是指某个点,将其删除后,可以使得剩余联通块的大小大的点。

也就等价于以某个点为根的树,将根删除后,剩余的若干颗子树的大小最小。

性质:

性质一

重心的若干颗子树的大小一定<=n;

除了重心以外的所有其他点,都必然存在一颗节点个数>n的子树。

性质二

一棵树至多有两颗重心,如果存在两个重心,则必然相邻;

将连接两个重心的边擦除后,一定划分为两颗大小相等的树;

性质三

树种所有点到某个点的距离和中,到重心的距离和是最小的;

如果有两个重心,那么它们的距离和一样。反过来,距离和最小的点一定是重心。

最后,树的重心问题可以处理一些最优化、最小化问题。

如何求解树的重心???

模板:

cpp 复制代码
void dif(int x, int y) {
	f[x] = 1, m[x] = 0;
	for (const auto& z : g[x]) {
		if (z == y) continue;
		dif(z, x);
		f[x] += f[z];
		m[x] = max(m[x], f[x]);
	}
	m[x] = max(m[x], n - f[x]);
	if (m[x] <= n / 2) v.push_back(x);
}
相关推荐
hqyjzsb2 小时前
零 AI 项目经验,学 Python 转型 AI 的正确顺序是什么?
开发语言·人工智能·python·算法·职场和发展·数据挖掘·数据分析
辰烨chenye2 小时前
LeetCode Hot 100 题解 · 二分篇
java·算法·leetcode
微功夫信息技术2 小时前
分层多智能体强化学习驱动的非急救转运公平 - 效率统一调度系统研究与实践
人工智能·学习·算法·动态规划
T1mzhou3 小时前
ARM64 Linux 6.10内核启动流程7-ioremap和readl writel
linux·服务器·c语言
sanjiaomao3333 小时前
从论文公式到Python实现:用单元测试校验滑动平均算法
python·算法·单元测试
Keven_113 小时前
算法札记:ACM适用的很骚的C++语法(持续更新)
开发语言·c++
乐迪信息3 小时前
如何通过AI防爆摄像机精准判断船舶超速?
大数据·人工智能·算法·安全·目标跟踪
mengzhi啊3 小时前
QPluginLoader 动态 DLL 插件版,支持插件之间通信,广播。请求和应答
c++·qt
雨落在了我的手上4 小时前
Java数据结构(十一):优先级队列(堆)
数据结构
大圣编蚕4 小时前
Java ByteArrayInputStream 详解:从入门到实战
java·开发语言·算法