CSP-S 2019 树的重心
小简单的课后作业是求出单独删去每条边后,分裂出的两个子树的重心编号和之和
请你帮小简单完成作业
subtask1
枚举删去哪一条边 然后找儿子 简单粗暴 时间复杂度
subtask2
扫过去 把重心弄出来就行了
std
有一个性质就是重心一定在这个树重链上 而且 每一个点的重儿子只有一个 很容易想到用倍增去写 然后我们可以一遍 边边换根 (和)的变化 时间复杂度
inline void work (int u) {
for (int i = 1; i <= 20; i ++ ) f[u][i] = f[f[u][i - 1]][i - 1];
}
inline void dfs (int u, int fa) {
size[u] = 1; Fa[u] = fa;
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (v == fa) continue;
dfs (v, u);
size[u] += size[v];
if (size[v] > size[son[u]]) son[u] = v;
}
f[u][0] = son[u];
work (u);
}
inline void solve (int u, int sz) {
for (int i = 20; i >= 0; i -- ) {
if (f[u][i] && size[f[u][i]] * 2 >= sz) u = f[u][i];
}
ans += u;
if (size[u] * 2 == sz) ans += Fa[u];
}
inline void dp (int u, int fa) {
int s1 = 0, s2 = 0;
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (size[v] > size[s1]) s2 = s1, s1 = v;
else if (size[v] > size[s2]) s2 = v;
}
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (v == fa) continue;
int x = s1;
if (v == x) x = s2;
size[u] -= size[v];
f[u][0] = x;
work (u);
solve (v, size[v]); solve (u, size[u]);
size[v] += size[u]; Fa[u] = v;
dp (v, u);
size[v] -= size[u]; size[u] += size[v];
}
f[u][0] = son[u];
work (u);
Fa[u] = fa;
}
分析
考场暴力标配 难度普及+
用倍增不难想主要是分析性质 想到重儿子就了 难度提高+
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)