乍一看好像挺简单的想都没想就开始建图...
直接忽略这是棵树...
然后做着做着就卡了
最后还是看了题解
不过真的挺简单的...人蠢嘛没办法
注意的地方大概就是dp特判和tree初始化不能为0吧
题目描述
有一棵二叉苹果树,如果数字有分叉,一定是分两叉,即没有只有一个儿子的节点。这棵树共 N 个节点,标号 1 至 N,树根编号一定为 1。
我们用一根树枝两端连接的节点编号描述一根树枝的位置。一棵有四根树枝的苹果树,因为树枝太多了,需要剪枝。但是一些树枝上长有苹果,给定需要保留的树枝数量,求最多能留住多少苹果。
输入格式
第一行两个数 N 和 Q ,N表示树的节点数,Q 表示要保留的树枝数量。
接下来 N−1 行描述树枝信息,每行三个整数,前两个是它连接的节点的编号,第三个数是这根树枝上苹果数量。
输出格式
输出仅一行,表示最多能留住的苹果的数量。
样例
样例输入
5 2
1 3 1
1 4 10
2 3 20
3 5 20
样例输出
21
数据范围与提示
对于 100%的数据,1≤Q≤N≤100,N≠1 , 每根树枝上苹果不超过 30000 个。
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int MAXN = 1e7 + 5 ; 5 6 int n , m , a , b , c ; 7 int left_son[105] , right_son[105] , apple[105] ; 8 int tree[105][105] , f[105][105] ; 9 10 int read(){ 11 char c ; 12 int sign = 1 ; 13 while((c = getchar()) < '0' || c > '9') 14 if(c == '-') sign = -1 ; 15 int Ans = c - '0' ; 16 while((c = getchar()) >= '0' && c <= '9') 17 Ans = Ans * 10 + c - '0' ; 18 return Ans * sign ; 19 } 20 21 void plant_tree(int a){ 22 for(int i = 1 ; i <= n ; ++ i) 23 if(tree[a][i] >= 0){ 24 left_son[a] = i ; 25 apple[i] = tree[a][i] ; 26 tree[a][i] = tree[i][a] = -1 ; 27 plant_tree(i) ; 28 break ; 29 } 30 for(int i = 1 ; i <= n ; ++ i) 31 if(tree[a][i] >= 0){ 32 right_son[a] = i ; 33 apple[i] = tree[a][i] ; 34 tree[a][i] = tree[i][a] = -1 ; 35 plant_tree(i) ; 36 break ; 37 } 38 } 39 40 int DP(int a , int k){ 41 if(k == 0) return 0 ; 42 if(left_son[a] == 0 && right_son[a] == 0) return apple[a] ;//理解f[a][k]是一定要取a这个点的 43 if(f[a][k]) return f[a][k] ; 44 for(int i = 0 ; i <= k - 1 ; ++ i){//最多只能到k-1 45 f[a][k] = max(f[a][k] , DP(left_son[a] , i) + DP(right_son[a] , k - i - 1) + apple[a]) ; 46 } 47 return f[a][k] ; 48 } 49 50 int main(){ 51 n = read() , m = read() ; 52 ++ m ; 53 for(int i = 1 ; i <= n ; ++ i){ 54 for(int j = 1 ; j <= n ; ++ j){ 55 tree[i][j] = -1 ; 56 } 57 } 58 for(int i = 1 ; i <= n - 1 ; ++ i){ 59 a = read() , b = read() , c = read() ; 60 tree[a][b] = tree[b][a] = c ;//双向边 61 } 62 plant_tree(1) ; 63 cout << DP(1 , m) ; 64 return 0 ; 65 }