树上的最远距离

1|0题目

1|1题目描述

给定一棵树,对于每一个点,输出离它最远的点到它的距离。

1|2输入格式

第一行包含整数 n

接下来 n1 行,每行包含两个整数 ai,bi,表示点 aibi 之间存在一条边。

1|3输出格式

输出一行 n 个整数,第 i 个数表示离节点 i 最远的点到它的距离。

1|4样例

1|0输入数据#1

8 1 5 1 4 6 3 2 6 6 1 3 7 4 8

1|0输出数据#2

3 4 4 4 4 3 5 5

1|5数据范围

  • 对于 20% 的数据:1n10
  • 对于 60% 的数据:1n103
  • 对于 100% 的数据:1n1051ai,bin

2|0思路分析

树的直径好题。

我们如果对每个点都跑一遍树的直径 dfs,时间复杂度 O(n2),超时。数据范围 n105 显然只允许我们跑一遍树的直径 dfs。

其实,我们只需先找到一条直径,然后对于每个点,比较两个端点哪个距离该点较远即可。

现在求点 u 最远的点到它的距离,记为 ans,跑树的直径 dfs 后得到直径 ab,分类讨论:

若点 u 不在直径 ab 的路径上,如下图:

反证法:

假设有点 v 是点 u 最远的点,距离为 s2+s4,直径的端点 a 到点 u 的距离为 s2+s3,则:

s2+s4>s2+s3

解得 s4>s3

所以 xv 的路径比 xa 的路径更长,直径则应为 s1+s4,与树的直径是 ab 矛盾,显然不存在。

若点 u 在直径 ab 的路径上:

证明如上,其中 s2=0,显然也不存在。

证毕。

3|0code

/*Written by smx*/ #include<bits/stdc++.h> using namespace std; #define int long long #define QAQ cout<<"QAQ\n"; const int MAXN=1e5+5,inf=1e18,mod=1e9+7; int n; vector<int> g[MAXN]; int dist[MAXN],d[MAXN]; int dfs(int now,int fa){ int ans=now; for(auto x:g[now]){ if(x==fa){ continue; } dist[x]=dist[now]+1; int d=dfs(x,now); if(dist[d]>dist[ans]){ ans=d; } } return ans; } signed main(){ //freopen(".in","r",stdin); //freopen(".out","w",stdout); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n; for(int i=1;i<n;i++){ int u,v; cin>>u>>v; g[u].push_back(v); g[v].push_back(u); } int u,v; u=dfs(1,0); dist[u]=0; v=dfs(u,0); for(int i=1;i<=n;i++){ d[i]=dist[i]; } dist[v]=0; dfs(v,0); for(int i=1;i<=n;i++){ cout<<max(d[i],dist[i])<<" "; } return 0; }

__EOF__

本文作者shimingxin1007
本文链接https://www.cnblogs.com/shimingxin1007/p/18585233.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   shimingxin1007  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示