如上图所示,比如要找距离3号点最远的结点。
1.可能是3到下边节点的路径,如3到5,3到6
2.可能是3到上边节点的路径
第2种情况又可以分为
2.1可能是3和父节点其他孩子之间的路径,如3->2->4
2.2可能3和父节点以上的节点的路径,如3->2->1
第一次dfs的时候,父节点可以通过孩子节点的信息,得到它向下的最远距离。
第二次dfs的时候,子节点可以通过父节点的信息,得到它向上的最远距离。
最后遍历所有节点取最小值就行。
代码如下
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N=1e4+10;
const int inf=0x3f3f3f3f;
struct edge{
int to;
int w;
};
int n;
vector<edge> v[N];
int d1[N],d2[N];
int p1[N],p2[N];//p代表经过的哪一支
int up[N];
bool isleaf[N];
int dfs_d(int u,int p)//往下找最远的边
{
d1[u]=d2[u]=-inf;
for(auto &t:v[u]){
if(t.to==p)continue;//代表向上到根节点
int d=dfs_d(t.to,u)+t.w;//这个孩子的最远距离
if(d>d1[u]){//这是最远的边
d2[u]=d1[u],d1[u]=d;
p2[u]=p1[u],p1[u]=t.to;
}
else if(d>d2[u]){
d2[u]=d,p2[u]=t.to;
}
}
if(d1[u]==-inf){//代表是叶子节点
isleaf[u]=true;
d1[u]=d2[u]=0;
}
return d1[u];
}
void dfs_u(int u,int p)
{
for(auto &t:v[u]){
if(t.to==p)continue;
if(p1[u]==t.to){//代表最长边是自己
up[t.to]=max(up[u],d2[u])+t.w;
}
else up[t.to]=max(up[u],d1[u])+t.w;
dfs_u(t.to,u);
}
}
int main()
{
cin>>n;
for(int i=0;i<n-1;i++){
int a,b,c;
cin>>a>>b>>c;
v[a].push_back({b,c});
v[b].push_back({a,c});
}
dfs_d(1,-1);
dfs_u(1,-1);
int ans=inf;
for(int i=1;i<=n;i++){
if(isleaf[i])ans=min(ans,up[i]);
else ans=min(ans,max(up[i],d1[i]));
}
cout<<ans<<endl;
}