loj10153. 「一本通 5.2 例 1」二叉苹果树

思路:
  先像树链剖分的第一次dfs一样求子树关系,再树形dp

#include<cstdio>
#include<iostream>
#include<string>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 110;
void qread(int &x){
    x = 0;
    register int ch = getchar();
    while(ch < '0' || ch > '9')    ch = getchar();
    while(ch >= '0' && ch <= '9')    x = 10 * x + ch - 48, ch = getchar();
}
int n, q;
int head[maxn];
int go[maxn << 1];
int val[maxn << 1];
int nxt[maxn << 1];

int f[maxn], l[maxn], r[maxn], deep[maxn], size[maxn], wor[maxn];

int dp[maxn][maxn];
void dfs(int x){
    size[x] = 1;
    for(register int i = head[x]; i; i =nxt[i]){
        if(!deep[go[i]]){
            f[go[i]] = x;
            deep[go[i]] = deep[x] + 1;
            wor[go[i]] = val[i];
            if(!l[x])    l[x] = go[i];
            else        r[x] = go[i];
            dfs(go[i]);
            size[x] += size[go[i]];
        }
    }
}
void init(){
    qread(n);
    qread(q);
    for(int i=1; i<n; ++i){
        int x, y, z;
        qread(x), qread(y), qread(z);
        go[i] = y;
        val[i] = z;
        nxt[i] = head[x];
        head[x] = i;
        go[i + n] = x;
        val[i + n] = z;
        nxt[n + i] = head[y];
        head[y] = n + i;
    }
    deep[1] = 1;
    dfs(1);
}
int DP(int i, int j){
    if(j == 0)    return 0;
    if(!l[i] && !r[i])    return wor[i];
    if(dp[i][j] > 0)    return dp[i][j];
    for(int k=0; k<=j-1; ++k)
        dp[i][j] = max(dp[i][j], DP(l[i], k) + DP(r[i], j - k - 1) + wor[i]);
    return dp[i][j];    
}
int main(void){
    init();
    printf("%d\n", DP(1, q + 1));
}

猜你喜欢

转载自www.cnblogs.com/junk-yao-blog/p/9491293.html