dp[ i ][ j ] = max ( dp[ i ][ j ] , dp[ i ][ j-k ] + dp[ s ][ k-1 ] + G[ x ][ s ] )
s 表示是 i 的兒子,G[ x ][ i ] 為該樹枝上的蘋果數、
我們可以想象一下,在 i 節點的子樹中,減去其兒子的 k 條邊,但不減去與兒子 s 節點的邊,就是隻減去了 k - 1 條邊
然後在實作的過程中,子樹的邊數是不好單獨求的,是以就在DFS中逐一求子樹的邊數
就用 sum += dfs( s , x ) 來求得邊數,在最後還要加一,應為還要算上自己的這條邊
代碼
結合代碼了解啦
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
using namespace std;
int n , m , dis[107][107] , dp[107][107] ;
vector <int> G[107] ;
int dfs( int x , int fa )
{
int sum = 0 ;
for(int i = 0 ; i < G[x].size() ; ++ i )
{
int s = G[x][i];
if( s == fa )
continue;
sum += dfs( s , x );//求邊數和
sum = sum + 1 ;
for(int j = m ; j >= 1 ; -- j ) {
for(int k = 1 ; k <= j ; ++ k ) {//邊數算上自己必須減去一條
dp[x][j] = max( dp[x][j] , dp[x][j-k] + dp[s][k-1] + dis[x][s] );
//轉移求最優解
}
}
}
return sum;
}
int main()
{
scanf("%d%d", &n , &m );
for(int i = 1 ; i < n ; ++ i )
{
int a , b ,c ;
scanf("%d%d%d", &a , &b , &c );
dis[a][b] = dis[b][a] = c ;//表示 a 到 b 的邊權
G[a].push_back(b);
G[b].push_back(a);
}
dfs( 1 , 0 );
printf("%d", dp[1][m] );
return 0;
}