树的中心 树形dp

 如上图所示,比如要找距离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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值