题目描述
有一棵苹果树,如果树枝有分叉,一定是分 2 叉(就是说没有只有 1 个儿子的结点)。 这棵树共有 N 个结点(叶子点或者树枝分叉点),编号为 1-N,树根编号一定是 1。 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有 4 个树枝 的树: 2 5 \ / 3 4 \ / 1 现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。 给定需要保留的树枝数量,求出最多能留住多少苹果。
输入格式:
第 1 行 2 个数,N 和 Q(1<=Q<= N,1<N<=100)。 N 表示树的结点数,Q 表示要保留的树枝数量。接下来 N-1 行描述树枝的信息。 每行 3 个整数,前两个是它连接的结点的编号。第 3 个数是这根树枝上苹果的数量。 每根树枝上的苹果不超过 30000 个。
输出格式:
一个数,最多能留住的苹果的数量。
输入样例:
5 2 1 3 1 1 4 10 2 3 20 3 5 20
输入样例:
21
代码实现
import java
.util
.ArrayList
;
import java
.util
.Scanner
;
public class Main {
public Main() {
Scanner sc
=new Scanner(System
.in
);
int N
,Q
; N
=sc
.nextInt(); Q
=sc
.nextInt();
int[][] Mat
=new int[N
+1][N
+1];
for(int i
=1;i
<=N
;i
++)
for(int j
=1;j
<=N
;j
++)
Mat
[i
][j
]=-1;
for(int i
=0;i
<N
-1;i
++) {
int x
,y
,weight
; x
=sc
.nextInt(); y
=sc
.nextInt(); weight
=sc
.nextInt();
Mat
[x
][y
]=Mat
[y
][x
]=weight
;
}
boolean[] Mark
=new boolean[N
+1];
ArrayList
[] Children
=new ArrayList[N
+1];
for(int i
=1;i
<=N
;i
++) Children
[i
]=new ArrayList<Integer>();
ArrayList
<Integer> Que
=new ArrayList<Integer>();
Que
.add(1); Mark
[1]=true; int front
=0;
while(front
<Que
.size()) {
int head
=Que
.get(front
); front
++;
for(int j
=1;j
<=N
;j
++)
if(Mat
[head
][j
]!=-1 && Mark
[j
]==false) {
Que
.add(j
); Mark
[j
]=true;
Children
[head
].add(j
);
}
}
int[][] Apple
=new int[N
+1][Q
+1];
for(int i
=Que
.size()-1;i
>=0;i
--) {
int a
=Que
.get(i
);
if(Children
[a
].size()!=0)
for(int q
=1;q
<=Q
;q
++) {
int max
=0;
int x
=(int) Children
[a
].get(0); int y
=(int) Children
[a
].get(1);
for(int q1
=0;q1
<=q
;q1
++) {
int current
; int q2
=q
-q1
;
if(q1
==0) current
=Apple
[y
][q2
-1]+Mat
[a
][y
];
else {
current
=Apple
[x
][q1
-1]+Mat
[a
][x
];
if(q2
!=0) current
+=Apple
[y
][q2
-1]+Mat
[a
][y
];
}
if(current
>max
) max
=current
;
}
Apple
[a
][q
]=max
;
}
}
System
.out
.println(Apple
[1][Q
]);
}
public static void main(String
[] args
) {
Main main
= new Main();
}
}