$ Luogu $ $ P2015 $ binary apple tree

link

background

\ (Luogu \) \ (P1122 / Codevs5565 \)

The meaning of problems

Given a \ (n-\) to nodes \ (1 \) dots as the root node of the tree \ (n-1 \) sides and weight \ ((x_i, y_i, W_i) \) , left after seeking to cut some of the branches \ (q \) maximum side and right edges.

solution

Nor is it a tree \ (dp \) template. Or exercises.
Because the tree is a binary tree, there is a beautiful nature: trees within a sub-tree branches reservations can only get around by the sub-tree (this is not bullshit you).
Considering the meaning of problems left conversion, some of the cut branches \ (Q \) edges i.e. left \ (q + 1 \) point and must contain the root.
Thus it can be set \ (f_ {x, i} \) represented by \ (X \) node subtree rooted left \ (I \) maximum points and edge weights.
This time it should continue to consider the topic of conversion. Because the root mandatory, so \ (n-1 \) sides can be converted into the remaining \ (n-1 \) weights points (each point to the edge weights of its parent). So the right side and became the largest maximum points and right.
Happily then be transferred: Let nodes \ (X \) left sons \ (L_x \) , the right son is \ (r_x \) , then \ (f_ {x, i} = \ max_ \ limits { J \ in [0,. 1-I]} \ {{L_x F_, F_ {+} J r_x,. 1-I-J} \} + val_x \) .
As \ (l_x \) and \ (r_x \)The method for finding, see below \ (trick \) it.

trick

A given \ (n-1 \) Article undirected edge \ (n (n \ leqslant 3 \ times 10 ^ 3) \) point binary tree root method for finding left and right child nodes:
establishing an adjacency matrix, but this to save as \ (int \) form, \ (G_ {X, Y} \) stored is \ ((x, y) \ ) of the right side.
Started to build from the root, recursively from top down.
The current node to each recursion \ (X \) are traversed when the \ (n-\) nodes, a first node has to find the right side of it as \ (L_x \) , then the recursive processing node. Directly after exiting the loop can be returned. Looking for \ (r_x \) Note To re-iterate \ (n \) nodes, find a node has a first right side of it as \ (r_x \) , then recursively processing the node.

detail

Note two boundaries: \ (F_ {X, 0} \) represents a group selected \ (0 \) node, the answer is bound \ (0 \) ; \ (L_x = 0 \) and \ (r_x = 0 \) ( that \ (x \) can not be selected sub-tree leaf nodes), the direct return to itself the right value.

Code

\(View\) \(Code\)

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int ret=0,f=1;
    char ch=getchar();
    while('9'<ch||ch<'0')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while('0'<=ch&&ch<='9')
    {
        ret=(ret<<1)+(ret<<3)+ch-'0';
        ch=getchar();
    }
    return ret*f;
}
int n,q,x,y,w,g[105][105],val[105],l[105],r[105],f[105][105];
void make_tree(int x)
{
    for(register int i=1;i<=n;i++)
    {
        if(g[x][i]||!g[x][i])
        {
            val[i]=g[x][i];
            g[x][i]=-1;
            g[i][x]=-1;
            l[x]=i;
            make_tree(i);
            break;
        }
    }
    for(register int i=1;i<=n;i++)
    {
        if(g[x][i]||!g[x][i])
        {
            val[i]=g[x][i];
            g[x][i]=-1;
            g[i][x]=-1;
            r[x]=i;
            make_tree(i);
            break;
        }
    }
}
int dp(int x,int cnt)
{
    if(!cnt)
        return 0;
    if((!l[x])&&(!r[x]))
        return val[x];
    if(f[x][cnt])
        return f[x][cnt];
    for(register int i=0;i<cnt;i++)
    {
        f[x][cnt]=max(f[x][cnt],dp(l[x],i)+dp(r[x],cnt-1-i)+val[x]);
    }
    return f[x][cnt];
}
int main()
{
    n=read();
    q=read();
    memset(g,-1,sizeof(g));
    for(register int i=1;i<n;i++)
    {
        x=read();
        y=read();
        w=read();
        g[x][y]=w;
        g[y][x]=w;
    }
    make_tree(1);
    printf("%d\n",dp(1,q+1));
    return 0;
}

Guess you like

Origin www.cnblogs.com/Peter0701/p/11838826.html