LOI 2015 二叉蘋果樹

題目描述

有一棵蘋果樹,如果樹枝有分叉,一定是分2叉(就是說沒有隻有1個兒子的結點)
這棵樹共有N個結點(葉子點或者樹枝分叉點),編號爲1-N,樹根編號一定是1。
我們用一根樹枝兩端連接的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹

2   5
 \ / 
  3   4
   \ /
    1

現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋果。給定需要保留的樹枝數量,求出最多能留住多少蘋果。

分析

典型的樹上dp問題,記fij 爲根爲i 的樹中選擇j 條邊最多能保留的果子數目
fij=max(fsonl,j1+wi,sonl,fsonr,j1+wi,sonr,fsonl,k+fsonr,j2k+wi,sonl+wi,sonr)
其中k 的範圍爲0j2

#include <bits/stdc++.h>
#define rep( i , l , r ) for( int i = (l) ; i <= (r) ; ++i )
#define per( i , r , l ) for( int i = (r) ; i >= (l) ; --i )
#define erep( i , u ) for( int i = head[(u)] ; ~i ; i = e[i].nxt )
using namespace std;
int _read(){
    char ch = getchar();
    int x = 0 , f = 1 ;
    while( !isdigit( ch ) )
           if( ch == '-' ) f = -1 , ch = getchar();
           else ch = getchar();
    while( isdigit( ch ) )
           x = (ch  - '0') + x * 10 , ch =  getchar();
    return x * f;
}
const int maxn = 100 + 5;
struct edge{
    int v , w , nxt;
}e[maxn * 2];
int f[maxn][maxn] , head[maxn] , _t = 0 , M = 0;
inline void cmax( int &a , int b ){
    a = a > b ? a : b;
}
void addedge( int u , int v , int w ){
    e[_t].v = v , e[_t].w = w , e[_t].nxt = head[u] , head[u] = _t++;
}
void dfs( int u , int fa ){
    int son[2][2] , cnt = 0 , v;
    erep( i , u ){
        v = e[i].v;
        if( v == fa ) continue;
        son[cnt][0] = v , son[cnt][1] = e[i].w; ++cnt;
        dfs( v , u ); 
    }
    if( cnt == 0 ) return;
    rep( j , 1 , M ){
        cmax( f[u][j] , f[ son[0][0] ][j - 1] + son[0][1] );
        cmax( f[u][j] , f[ son[1][0] ][j - 1] + son[1][1] );
        if( j >= 2 )
            rep( k , 0 , j - 2 )
                cmax( f[u][j] , f[ son[0][0] ][k] + f[ son[1][0] ][j - 2 - k] + son[0][1] + son[1][1] );
    }
}
int main(){
    memset( head , 0xff , sizeof head );
    int N = _read(); M = _read();
    int u , v , w;
    rep( i , 1 , N - 1 ){
        u = _read() , v = _read() , w = _read();
        addedge( u , v , w );
        addedge( v , u , w );
    }
    dfs( 1 , 0 );
    cout << f[1][M] << endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章