当前位置: 首页 > news >正文

洛谷 P10962:Computer ← 换根DP

【题目来源】
https://www.luogu.com.cn/problem/P10962
http://acm.hdu.edu.cn/showproblem.php?pid=2196

【题目描述】
某学校在一段时间前购买了第一台计算机(因此这台计算机的编号是 1)。在最近几年中,学校又购买了 N-1 台新计算机。每台新计算机都连接到之前已经安装的计算机之一。学校的管理人员对网络运行缓慢感到担忧,想知道每台计算机需要发送信号的最大距离 Si(即到最远计算机的电缆长度)。你需要提供这些信息。

P10962

提示:示例输入对应于此图。从图中可以看到,计算机 4 是距离计算机 1 最远的,因此 S1=3。计算机 4 和 5 是距离计算机 2 最远的,因此 S2=2。计算机 5 是距离计算机 3 最远的,因此 S3=3。我们还得到 S4=4,S5=4。

【输入格式】
输入文件包含多个测试用例。每个用例的第一行是自然数 N(N≤10000),接下来的 N-1 行描述了计算机的连接情况。第 i 行(i≥2)包含两个自然数 --- 第 i 台计算机连接的计算机编号和用于连接的电缆长度。电缆的总长度不超过 10^9。输入行中的数字由空格分隔。

【输出格式】
对于每个用例,输出 N 行。第 i 行必须包含第 i 台计算机的数值 Si(1≤i≤N)。

【输入样例】
5
1 1
2 1
3 1
1 1​​​​​​​

【输出样例】
3
2
3
4
4

【数据范围】
N≤10000,1≤i≤N

【算法分析】
● 换根 DP 是树形 DP 的一种重要技术,用于解决需要以树中‌不同节点为根‌分别计算答案的问题。其核心思想是在一次动态规划后,通过‌推导出换根时的状态转移公式‌,高效地计算出所有节点作为根时的结果,避免对每个根节点都进行一次 O(n) 的树形DP(那样总复杂度为 O(n²))。

● 对于大多数简单的树形 DP 问题,如计算子树大小、节点深度、简单路径统计等,算法通常对每个节点执行常数次操作,因此时间复杂度为 ‌O(n)‌。

● 换根 DP 通常遵循一个固定的两遍 DFS 流程:
(一)第一次 DFS(固定根,收集信息)‌
(1)任选一个节点(通常为 1 号节点)作为初始根。
(2)进行一次自底向上的树形 DP,计算以该节点为根时,各子树的状态信息。这些信息通常包括:子树大小(siz[u])、子树内节点到根的距离和(dis[u])、或其他与问题相关的子树最优解。
(二)第二次 DFS(换根,推导全局)‌
(1)这是算法的关键。基于第一次 DFS 得到的信息,从初始根节点开始,进行第二次 DFS。
(2)在遍历过程中,当从父节点 u 走向子节点 v 时,利用已知的以 u 为根时的全局答案 dp[u],推导出以 v 为根时的全局答案 dp[v]。
(3)这个推导过程就是 ‌“换根公式”‌,它分析了当根从 u 移到 v 时,哪些节点的贡献发生了变化(例如,深度增加或减少),并据此更新答案。

● 经典示例:所有节点到其他节点距离之和
​​​​​​​代码详见:https://blog.csdn.net/hnjzsyjyj/article/details/157169859
这是一个最经典的换根DP问题,清晰地展示了换根公式的推导过程。
(1)问题‌:给一棵树,求以每个节点为根时,所有节点到该根节点的深度之和。
(2)定义‌:siz[u]:以 u 为根的子树中的节点数、dis[u]:以 u 为根时,所有节点到 u 的深度之和。

P3478_1

(3)步骤‌:
第一次 DFS‌:以节点 1 为根,计算 siz[u] 和初始的 dis[1]。
换根公式推导‌:当根从 u 换到其子节点 v 时,所有在 v 子树中的节点,到新根 v 的距离比到旧根 u 的距离‌减少1‌。这部分贡献总共减少 siz[v]。所有不在 v 子树中的节点(共 n - siz[v] 个),到新根 v 的距离比到旧根 u 的距离‌增加1‌。这部分贡献总共增加 n - siz[v]。
因此,dis[v] = dis[u] - siz[v] + (n - siz[v]) = dis[u] + n - 2 * siz[v]。
第二次 DFS‌:应用此公式,即可从 dp[1] 递推计算出所有节点的 dis[i]。

● 本题数据量达到了 10^4,可以在代码中加入如下语句(https://blog.csdn.net/hnjzsyjyj/article/details/143176072),避免 TLE。

ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);

当然,也可以使用“快读(https://blog.csdn.net/hnjzsyjyj/article/details/120131534)”函数,代码如下。

int read() { //fast readint x=0,f=1;char c=getchar();while(c<'0' || c>'9') { //!isdigit(c)if(c=='-') f=-1;c=getchar();}while(c>='0' && c<='9') { //isdigit(c)x=x*10+c-'0';c=getchar();}return x*f;
}

● 本题输入样例解释
第 1 行,5,树的总节点数 n=5(节点编号为 1~5)。
第 2 行,1 1,对应节点 2,它的父节点是 1,与父节点之间的边权为 1。
第 3 行,2 1,对应节点 3,它的父节点是 2,与父节点之间的边权为 1。
第 4 行,3 1,对应节点 4,它的父节点是 3,与父节点之间的边权为 1。
第 5 行,1 1,对应节点 5,它的父节点是 1,与父节点之间的边权为 1。​​​​​​​

【算法代码】

#include <bits/stdc++.h>
using namespace std;const int N=1e4+5;
int f[N]; //Local (subtree) longest
int g[N]; //Local (subtree) secondary length
int dis[N]; //Globally (tree) longest
int val[N<<1],e[N<<1],ne[N<<1],h[N],idx;
int n;void add(int a,int b,int w) {val[idx]=w,e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}void dfs1(int u) {for(int i=h[u]; i!=-1; i=ne[i]) {int j=e[i],v=val[i];dfs1(j);if(f[j]+v>f[u]) g[u]=f[u],f[u]=f[j]+v;else if(f[j]+v>g[u]) g[u]=f[j]+v;}
}void dfs2(int u,int t) {dis[u]=max(t,f[u]);int fir=max(t,f[u]),sec=max(t,g[u]);for(int i=h[u]; i!=-1; i=ne[i]) {int j=e[i],v=val[i];if(f[j]+v==f[u]) dfs2(j,sec+v);else dfs2(j,fir+v);}
}int main() {while(cin>>n) {memset(h,-1,sizeof h);idx=0;for(int i=1; i<=n; i++) f[i]=g[i]=0;for(int i=2; i<=n; i++) {int x,w;cin>>x>>w;add(x,i,w);}dfs1(1);dfs2(1,0);for(int i=1; i<=n; i++) {cout<<dis[i]<<endl;}}return 0;
}/*
in:
5
1 1
2 1
3 1
1 1out:
3
2
3
4
4
*/





【参考文献】
https://mp.weixin.qq.com/s/Ulg9GIl0u2Qgh45FnC9OMg
https://blog.csdn.net/hnjzsyjyj/article/details/157169859
https://blog.csdn.net/hnjzsyjyj/article/details/157134513
https://www.cnblogs.com/mingloch/p/17678247.html
https://www.luogu.com.cn/problem/solution/P10962



 

http://www.jsqmd.com/news/275069/

相关文章:

  • SCADA与数字孪生(Digital Twin)系统的异同点在哪里?
  • AI狂飙与冷思考:一个准码农的2026开年观察
  • 完整教程:人机交互(如 VR 手柄追踪、光标移动、手势识别)的滤波算法
  • 【读书笔记】《稻盛和夫自传》
  • 《把脉行业与技术趋势》-65-当你的人生轨迹与民族复兴的长波、技术革命的中波、行业爆发的短波同频共振时,平凡的努力,也会被时代放大成非凡的成就——这,便是“着道”的现代诠释。
  • AI生成SQL的安全风险与测试框架
  • 线段树合并
  • 454. 四数相加 II-day06
  • 《把脉行业与技术趋势》-69-股票的周期、产品的周期、企业的周期的相似性与不同,以及它们各自在不同阶段关注的重点和核心要素不同
  • 大数据毕设选题推荐:基于大数据技术的Django框架下的学习资源推送系统的设计与实现基于Django+大数据的学习资源推送系统【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 若思中国发布2026年十大最具影响力战略咨询大师推荐榜 - 资讯焦点
  • 大模型测试的“评估指标”:BLEU?ROUGE?都不够!
  • 互联网大厂Java面试场景:分布式系统与微服务架构
  • 品牌整合营销战略咨询公司哪家靠谱? - 资讯焦点
  • 寒假学习笔记1.18
  • ‌构建“大模型测试沙箱”:隔离、监控、审计的工程实践指南
  • 含分布式电源的配电网日前两阶段优化调度模型-无功优化Matlab代码
  • 多模态RAG不止知识问答:文搜图与图搜图的四种实现方案
  • 大数据计算机毕设之基于Django的在线学习资源分享与推荐系统基于Django+大数据的学习资源推送系统(完整前后端代码+说明文档+LW,调试定制等)
  • kotlin 类委托
  • ‌大模型测试必须包含“多轮对话压力测试”
  • 58、IMX6ULL 裸机开发实战:从汇编启动代码到 LED 闪烁(Ubuntu 篇)
  • MySQL常用命令
  • 【完整版代码】含分布式电源的配电网日前两阶段优化调度模型Matlab代码
  • 如何自动化检查服务器的高危端口
  • ‌如何测试AI的“长上下文记忆”?
  • Flutter---Scrollable
  • 基于蒙特卡洛的风电功率/光伏功率场景生成方法Matlab代码
  • 大数据毕设项目:基于django的蔬菜销售分析与预测可视化系统(源码+文档,讲解、调试运行,定制等)
  • 告别GPU依赖:深度剖析AI推理芯片市场,谁将主宰终端智能?