1005 树上自链 最大链和次大链

链接:https://ac.nowcoder.com/acm/contest/25022/1005
来源:牛客网

题目描述

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

输入描述:

第一行输入一个 n,1≤n≤105n,1 \le n \le 10^5n,1n105。
接下来一行包含n个数,对于每个数 ai,−105≤ai≤105a_i, -10^5 \le a_i \le 10^5ai,105ai105,表示 i 结点的权值。
接下来有n-1行,每一行包含两个数u,v( 1≤u,v≤n1 \le u,v \le n1u,vn , u != v),表示u与v之间有一条边。

输出描述:

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

输入

复制
5
2 -1 -1 -2 3
1 2
2 3
2 4
2 5

输出

复制
4

说明

样例中最大子链为1 -> 2 -> 5

备注:

一个结点,也可以称作一条链

 

分析

算上最大值和次大值,然后最大化一条链就可以了。

#include<bits/stdc++.h>
#define V vector
using namespace std;
#define int long long
const int N = 1e5+10;
int a[N];
long long sz[N];
V<int> g[N];
bool st[N];
int ans = -0x3f3f3f3f;
void dfs(int u,int fa) {
//     cout<<u<<endl;
    long long res = 0;
    long long res2 = 0;
    for(int i = 0;i<g[u].size();i++) {
        int j = g[u][i];
        if(j == fa) continue;
        dfs(j,u);
        if(sz[j] > res) {
            res2 = res;
            res = sz[j];
        } else if( sz[j] > res2) {
            res2 = sz[j];
        }
    }
    ans = max(a[u] + res + res2,ans);
    if(ans == 1) cout<<u<<' '<<res<<' '<<res2<<' '<<endl;
    if(res != -0x3f3f3f3f)sz[u] += res;
    sz[u] += a[u];
//     if(u == 2) cout<<res<<' '<<sz[u]<<endl;
//     if(u == 1) cout<<res<<' '<<sz[u]<<endl;
//     if(u == 1) {
//         cout<<a[u]<<endl;
//     }
}

signed main() {
    int n;
    cin>>n;
    for(int i = 1;i<= n;i ++ ) cin>>a[i];
    for(int i = 1;i< n;i ++ )
    {
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(1,0);
    cout<<ans<<endl;
}

 

posted @ 2022-08-01 20:31  er007  阅读(25)  评论(0编辑  收藏  举报