树上子链(树形dp,树的直径)

树上子链

题目链接
给定一棵树 T ,树 T 上每个点都有一个权值。
定义一颗树的子链的大小为:这个子链上所有结点的权值和 。
请在树 T 中找出一条最大的子链并输出。

输入描述:

第一行输入一个 n,1≤n≤105
接下来一行包含n个数,对于每个数 ai,-105<=ai<=105
,表示 i 结点的权值。
接下来有n-1行,每一行包含两个数u,v(1≤u,v≤n , u != v),表示u与v之间有一条边。

输出描述:

仅包含一个数,表示我们所需要的答案。
示例1

输入

5
2 -1 -1 -2 3
1 2
2 3
2 4
2 5

输出

4

说明

样例中最大子链为1 -> 2 -> 5
备注:
一个结点,也可以称作一条链

算法分析

树形dp求树的直径的模板题,dfs从头结点出发,每遇到一个点就遍历他的子树,之后回馈,合成该子树的权值和.整个过程是用顶点出发,但是是从下到上更新,就是一个结点更新,他的子树一定更新过了

代码实现

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e5+5;
typedef long long ll;
int head[maxn],to[maxn*2],nex[maxn*2],idx;
int a[maxn];
ll dp[maxn];
ll ans=-0x3f3f3f3f;
void add(int a,int b)
{
    to[idx]=b,nex[idx]=head[a],head[a]=idx++;
}
void dfs(int u,int fa)
{
    dp[u]=a[u];
    ans=max(ans,dp[u]);
    for(int i=head[u];i!=-1;i=nex[i])
    {
        int j=to[i];
        if(j!=fa)
        {
            dfs(j,u);                    //从下往上反馈
            ans=max(ans,dp[u]+dp[j]);    //判断连接的最大值
            dp[u]=max(dp[u],dp[j]+a[u]); //更新头结点最大值
        }
    }
}
int main()
{
    int n;
    cin>>n;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n;i++)
       cin>>a[i];
    for(int  i=1;i<=n-1;i++)
    {
        int a,b;
        cin>>a>>b;
        add(a,b);
        add(b,a);
    }
    dfs(1,0);
    cout<<ans<<endl;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值