树形dp之树的直径

题目:树上子链

树的最长子链(直径)= 以根为终点的最长子链 + 以根为终点的次长子链
f[i]表示以 i(根)为终点的最长子链

//树的直径有两种求法 
//1.树形DP(可以有效处理负边权)
//2.两次dfs或bfs(无法处理负边权)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll const INF=0x3f3f3f3f3f3f3f3f;
int const N=1e5+7;
int n,cnt;
int head[N];
struct node{
    int a,next,len;
}edge[N<<1];
void add(int x,int y,int len){
    edge[++cnt].a =y;
    edge[cnt].len =len;
    edge[cnt].next =head[x];
    head[x]=cnt;
}
ll p[N],vis[N],f[N],ans=-INF;
void dfs(int x){
    f[x]=p[x];
    vis[x]=1;
    ll z1=-INF,z2=-INF;
    for(int i=head[x];i!=-1;i=edge[i].next){
        int u=edge[i].a ;
        if(vis[u]) continue;
        vis[u]=1;
        dfs(u);
        if(f[u]>z2){
            if(f[u]>z1){
                z2=z1;
                z1=f[u];
            }
            else z2=f[u];
        }
    }
    ll z=max(f[x],max(z1+f[x],z1+z2+f[x]));
    ans=max(ans,z);
    f[x]=max(f[x],f[x]+z1);
    //f[x]=max(f[x],z);
    //cout << x << " " << f[x] << endl;
}
int main(){
    cin >> n;
    memset(head,-1,sizeof(head));
    memset(f,-0x7f,sizeof(f));
    for(int i=1;i<=n;++i){
        int a;
        cin >> a;
        p[i]=a;
    }
    for(int i=1;i<=n-1;++i){
        int a,b;
        cin >> a >> b;
        add(a,b,0);add(b,a,0);
    }
    dfs(1);
    cout << ans ;
    return 0;
} 
全部评论

相关推荐

头像
05-16 11:16
已编辑
东华理工大学 Java
牛客737698141号:盲猜几十人小公司,庙小妖风大,咋不叫她去4️⃣呢😁
点赞 评论 收藏
分享
后来123321:别着急,我学院本大二,投了1100份,两个面试,其中一个还是我去线下招聘会投的简历,有时候这东西也得看运气
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务