树上最长子链

树形DP求树的直径

设D[x]表示从结点x出发,走向以x为根的子树,能够到达的最短距离,设x的子结点 y 1 , y 2 . . . y t y_1,y_2...y_t y1,y2...yt,则有
D [ x ] = m a x ( D i + e d g e ( x , y i ) ) i = 1 , 2 , . . . t D[x] = max ( D_i + edge(x, y_i) ) i = 1,2,...t D[x]=max(Di+edge(x,yi))i=1,2,...t
定义F[x]为经过x的最长链的长度,对于x的任意两个结点 y i , y j y_i,y_j yi,yj,F[x]由四部分构成,从 y i y_i yi y i y_i yi子树的最远距离,边 ( x , y i ) (x, y_i) (x,yi),边 ( x , y j ) (x, y_j) (x,yj) y j y_j yj y j y_j yj子树的最远距离。

code

void dp(int x)
{
    v[x] = 1;
    for(int i = head[x]; i; i = net[i])
    {
        int y = ver[i];
        if(v[y])
            continue;
        dp(y);
        ans = max(ans, d[x] + d[y] + edge[i]);
        d[x] = max(d[x], d[y] + edge[i]);
    }
}

例题

添加链接描述

说明

此处给出的是每个结点的权值,并不是每条边的权值,但是求法与求树的直径差不多

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 1E5+5;
vector<ll> vec[N];
ll n, a[N], dp[N], ans = -1E9;
void dfs(ll x, ll fa)
{
    dp[x] = a[x];
    for(ll i = 0; i < vec[x].size(); i++)
    {
        ll y = vec[x][i];
        if(y == fa)
            continue;
        dfs(y, x);
        ans = max(ans, dp[x] + dp[y]);
        dp[x] = max(dp[x], dp[y] + a[x]);
    }
    ans = max(ans, dp[x]);
}
int main()
{
    scanf("%lld", &n);
    for(ll i = 1; i <= n; i++)
        scanf("%lld", &a[i]);
    for(ll i = 1; i < n; i++)
    {
        ll u, v;
        scanf("%lld%lld", &u, &v);
        vec[u].push_back(v);
        vec[v].push_back(u);
    }
    dfs(1, 0);
    cout << ans << endl;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值