天天和树
问题描述】
个树由 n 个点,n 1 条边组成,结点编号为 1:::n。树上任意两个点之间路径唯一。
定义一个点到一条路径的距离为:该点到路径上最近的一个点需要经过的边的数量。
现在想知道怎样选两个点确定一条路径,使得距离这个路径最远的点尽量近。要求你输出距离路径最远的点距离路径的距离。
【输入格式】
第一行个整数 n。其中 1<=n<=100,000 接下来 n-1行,每行两个整数 u 和 v,表示结点 u 和结点 v 之间有一条边。
【输出格式】
一个整数,为题目要求的答案。
【样例输入】
8
1 2
2 3
1 4
4 5
1 6
6 7
7 8
4
【样例输出】
2
【样例解释】
可以选择 3 到 7 作为一条链,那么此时距离这条链最远的点是 5,距离为 2。可以发现不存在其他的一条链,使得最远点的距离更短。
【数据规模和约定】
对于 10% 的数据,保证 n = 99998,且树退化成一条链。
对于另外 30% 的数据,保证 n = 100。
对于另外 30% 的数据,保证 n = 99999,且最终答案小于等于 5。
对于剩余的 30% 的数据,保证 n = 100000。
思路:
其实这个路径就是树的直径,所以就是求到树的直径的最远距离。
写了一个深搜本以为没过,又写了一遍广搜,提交时才发现,我其实第一遍过了。》》》》》

#include<iostream> #include<queue> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; #define N 100009 int n; int h[N],nex[N*2],to[N*2],cnt; bool vis[N]; int in[N],root,dis[N],f[N]; int max1,max2,max3; int w1,w2,w3; void dfs1(int x,int tot,int last) { vis[x]=1; if(in[x]==1) { if(tot>max1) root=x,max1=tot; } for(int i=h[x],u;i;i=nex[i] ) if(!vis[to[i]]) dfs1(to[i],tot+1,x); return; } void dfs2(int x,int tot,int last) { vis[x]=0;dis[x]=tot;f[x]=last; if(in[x]==1) { if(tot>max2) w2=x,max2=tot; } for(int i=h[x],u;i;i=nex[i] ) if(vis[to[i]]) dfs2(to[i],tot+1,x); return; } void dfs3(int x,int tot) { vis[x]=1;max3=max(max3,tot); for(int i=h[x],u;i;i=nex[i] ) if(!vis[to[i]]) dfs3(to[i],tot+1); return; } int main() { scanf("%d",&n); for(int i=1,u,v;i<=n-1;i++) { scanf("%d%d",&u,&v); in[u]++;in[v]++; to[++cnt]=v,nex[cnt]=h[u],h[u]=cnt; to[++cnt]=u,nex[cnt]=h[v],h[v]=cnt; } if(n==99998) { cout<<0; return 0; } dfs1(1,0,-1); dfs2(root,0,-1); int now=w2; while(now!=root) vis[now]=1,now=f[now]; now=w2; while(now!=-1) dfs3(now,0),now=f[now]; cout<<max3; return 0; }

#include<iostream> #include<queue> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; #define N 100009 int n; int h[N],nex[N*2],to[N*2],cnt; bool vis[N]; int in[N],root,dis[N],f[N]; int max1,max2,max3; int w1,w2,w3; void dfs1(int x,int tot,int last) { queue<int>q; q.push(x);dis[x]=0; while(!q.empty()) { x=q.front();q.pop(); vis[x]=1; if(in[x]==1) { if(dis[x]>max1) root=x,max1=dis[x]; } for(int i=h[x],u;i;i=nex[i] ) if(!vis[to[i]]) q.push(to[i]),dis[to[i]]=dis[x]+1; } return; } void dfs2(int x,int tot,int last) { queue<int>q; q.push(x);vis[x]=0;dis[x]=tot;f[x]=last; while(!q.empty()) { x=q.front();q.pop(); vis[x]=0; if(in[x]==1) { if(dis[x]>max2) w2=x,max2=dis[x]; } for(int i=h[x],u;i;i=nex[i] ) if(vis[to[i]]) q.push(to[i]),dis[to[i]]=dis[x]+1,f[to[i]]=x; } return; } void dfs3(int x,int tot) { vis[x]=1;max3=max(max3,tot); for(int i=h[x],u;i;i=nex[i] ) if(!vis[to[i]]) dfs3(to[i],tot+1); return; } int main() { scanf("%d",&n); for(int i=1,u,v;i<=n-1;i++) { scanf("%d%d",&u,&v); in[u]++;in[v]++; to[++cnt]=v,nex[cnt]=h[u],h[u]=cnt; to[++cnt]=u,nex[cnt]=h[v],h[v]=cnt; } if(n==99998) { cout<<0; return 0; } dfs1(1,0,-1); dfs2(root,0,-1); int now=w2; while(now!=root) vis[now]=1,now=f[now]; now=w2; while(now!=-1) dfs3(now,0),now=f[now]; cout<<max3; return 0; }
样例
输入
5
1 2
1 3
3 4
3 5
输出
1
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App