【P2015】 二叉苹果树 树形dp第一题

P2015
这是严格意义上我学习的树形dp第一题
因为是二叉树 满足很好的传递性 就可以在树上做dp 了 相当于你取不取 取m个 那么肯定就是背包问题
只不过这个背包在树上1连着的那条边所有的边都不能去 也就是说 你一旦选了一个点做爸爸 那么肯定这个点和一直接是有边连着的 不然选这个没意义
所以我们看第一重循环 j是要取 m i n ( s z [ x ] , m ) min(sz[x],m) min(sz[x],m)但是 j j j不能取0 因为你j一定要有一条边是和父亲连的
所以下面k-1其实也是为了让当前 x x x 和他的儿子 t o to to需要连边

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<#define dbg3(x1,x2,x3) cout<<#x1<<" = "<#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))

typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
const int MAX_N = 105;
ll dp[MAX_N][MAX_N];
int sz[MAX_N];
vector<pll> G[MAX_N];
int n,m;
void dfs(int x,int fa)
{
    int SZ = G[x].size();
    for(int i = 0;i<SZ;++i)
    {
        int to = G[x][i].first;
        if(to==fa) continue;
        dfs(to,x);
        sz[x]+=sz[to]+1;
        for(int j = min(m,sz[x]);j;j--)
            for(int k = min(sz[to],j-1);k>=0;k--)
                dp[x][j] = max(dp[x][j],dp[x][j-k-1]+dp[to][k]+G[x][i].second);
    }
}
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int a,b,v;
    scanf("%d%d",&n,&m);
    for(int i = 1;i<n;++i)
    {
        scanf("%d%d%d",&a,&b,&v);
        G[a].push_back(pll(b,v));
        G[b].push_back(pll(a,v));
    }
    dfs(1,-1);
    printf("%lld\n",dp[1][m]);
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

你可能感兴趣的:(ACM,树形dp,DP)