链接:https://ac.nowcoder.com/acm/contest/4462/B
来源:牛客网
题目描述
给定一棵树 T ,树 T 上每个点都有一个权值。定义一颗树的子链的大小为:这个子链上所有结点的权值和 。
请在树 T 中找出一条最大的子链并输出。
输入描述:
第一行输入一个 n,1<=n<=10^5
接下来一行包含n个数,对于每个数 ai, 表示 i 结点的权值。
接下来有n-1行,每一行包含两个数u,v,表示u与v之间有一条边。
输出描述:
仅包含一个数,表示我们所需要的答案。
示例1
输入
5
2 -1 -1 -2 3
1 2
2 3
2 4
2 5
输出
4
说明
样例中最大子链为1 -> 2 -> 5
备注:
一个结点,也可以称作一条链
题解:寻找最长半径(树形DP)不知道为什么只是过了70%用例
import java.util.*;
import java.util.List;
import java.util.ArrayList;
public class 牛客小白月赛22B树上子链 {
public static int maxn=200000;
public static long num[]=new long [maxn];
public static long vis[]=new long [maxn];
public static List<Integer> list[]=new List[maxn];
public static long ans=Long.MIN_VALUE;
public static void dfs(int now,int fa) {
long max1=0;
long max2=0;
for(int i=0;i<list[now].size();i++) //由now结点出发寻找子树的最大值和次最大值(不包括now结点的权值)
{
if(list[now].get(i)==fa) {
continue;
}
dfs(list[now].get(i),now);
if(max1<vis[list[now].get(i)]) {
max2=max1;
max1=vis[list[now].get(i)];
}else if(max2<vis[list[now].get(i)]) {
max2=vis[list[now].get(i)];
}
}
vis[now]=max1+num[now];
ans=Math.max(max1+max2+num[now],ans);
}
public static void main(String[] args)
{
Scanner sc =new Scanner(System.in);
int n=sc.nextInt();
for(int i=1;i<=n;i++) {
num[i]=sc.nextLong();
list[i]=new ArrayList<Integer>();
}
for(int i=1;i<=n-1;i++) {
int x,y;
x=sc.nextInt();
y=sc.nextInt();
list[x].add(y);
list[y].add(x);
}
dfs(1,-1);
System.out.println(ans);
}
}