问题描述
有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少?
输入格式
第一行包含一个整数 n 。
接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。
接下来一共 n-1 行,每行描述树上的一条边。
输出格式
输出一个整数,代表选出的点的权值和的最大值。
样例输入
5
1 2 3 4 5
1 2
1 3
2 4
2 5
样例输出
12
样例说明
选择3、4、5号点,权值和为 3+4+5 = 12 。
数据规模与约定
对于20%的数据, n <= 20。
对于50%的数据, n <= 1000。
对于100%的数据, n <= 100000。
权值均为不超过1000的正整数。
c++写的可以通过,但Java卡在了后三个测试数据
java版
import java.util.*;
public class Main{
//public static List<List<Integer>> l=new ArrayList<List<Integer>>();//定义一个动态二维数组
public static Vector<Vector<Integer>>l=new Vector<Vector<Integer>>();
static int [][]dp=new int[100002][2];
public static void main(String []args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
//l.add(new ArrayList<Integer>());
l.add(new Vector<Integer>());
for(int i=1;i<=n;i++)
{
dp[i][1]=sc.nextInt();
//l.add(new ArrayList<Integer>());//分配空间
l.add(new Vector<Integer>());
}
for(int i=1;i<n;i++) {
int x=sc.nextInt();
int y=sc.nextInt();
l.get(x).add(y);//父节点连接子节点
l.get(y).add(x);//子节点连接父节点
}
dfs(1,0);
System.out.print(Math.max(dp[1][1], dp[1][0]));
}
public static void dfs(int x,int y) {
for(int i=0;i<l.get(x).size();i++) {
Integer ls=l.get(x).get(i);
if(ls!=y) {
dfs(ls,x);
dp[x][1]+=dp[ls][0];
dp[x][0]+=Math.max(dp[ls][0], dp[ls][1]);
}
}
}
}
c++版
#include"iostream"
#include"vector"
using namespace std;
vector<vector<int> >tree;
int dp[100002][2];
void dfs(int x,int y){
for(int i=0;i<tree[x].size();i++)
{
int x_c=tree[x][i];
if(x_c!=y){
dfs(x_c,x);
dp[x][1]+=dp[x_c][0];
dp[x][0]+=max(dp[x_c][1],dp[x_c][0]);
}
}
}
int main(){
int n,i;
cin>>n;
for(i=1;i<=n;i++)
cin>>dp[i][1];
tree.resize(n+1);
int x,y;
for(i=1;i<n;i++)
{
cin>>x>>y;
tree[x].push_back(y);
tree[y].push_back(x);
}
dfs(1,0);
cout<<max(dp[1][1],dp[1][0])<<endl;
return 0;
}