1005 树上自链 最大链和次大链
链接:https://ac.nowcoder.com/acm/contest/25022/1005
来源:牛客网
题目描述
给定一棵树 T ,树 T 上每个点都有一个权值。
定义一颗树的子链的大小为:这个子链上所有结点的权值和 。
请在树 T 中找出一条最大的子链并输出。
输入描述:
第一行输入一个 n,1≤n≤105n,1 \le n \le 10^5n,1≤n≤105。
接下来一行包含n个数,对于每个数 ai,−105≤ai≤105a_i, -10^5 \le a_i \le 10^5ai,−105≤ai≤105,表示 i 结点的权值。
接下来有n-1行,每一行包含两个数u,v( 1≤u,v≤n1 \le u,v \le n1≤u,v≤n , u != v),表示u与v之间有一条边。
输出描述:
仅包含一个数,表示我们所需要的答案。
备注:
一个结点,也可以称作一条链
分析
算上最大值和次大值,然后最大化一条链就可以了。
#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; }