HDU4616 Game (TYOI summer camp D1 · H)

#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=50005;
int t,n,c,val[N],tp[N],dp[N][5][2],ans,u,v;
std::vector<int> mp[N];
/*
    树形dp,dp[][][1]表示向子节点,dp[][][0]表示向根节点
    用dfs确定转移顺序,存现节点与上一节点确保不会返回
    如果u点有陷阱,那么dp[now][1][1]不能由dp[nex][0][1]转移过来,因为一旦限制为1,那么就不能由now往叶子方向走了
    我们在求最大值是会用到dp[now][0][1]的,怎么办呢?我们发现dp[now][0][1]是可以由dp[now][0][0]代替的。
*/
inline void dfs(int now,int pre)
{
    dp[now][tp[now]][1]=dp[now][tp[now]][0]=val[now];
    for(int i=0;i<mp[now].size();i++)
    {
        int nex=mp[now][i];
        if(nex==pre)continue;
        dfs(nex,now);
        for(int j=0;j<=c;j++)for(int k=0;j+k<=c;k++)
        {
            if(j<c)ans=max(ans,dp[now][j][0]+dp[nex][k][1]);
            if(k<c)ans=max(ans,dp[now][j][1]+dp[nex][k][0]);
            if(j+k<c)ans=max(ans,dp[now][j][0]+dp[nex][k][0]);
        }
        for(int j=0;j<=c;j++)
        {
            dp[now][j+tp[now]][0]=max(dp[now][j+tp[now]][0],dp[nex][j][0]+val[now]);
            if(j)dp[now][j+tp[now]][1]=max(dp[now][j+tp[now]][1],dp[nex][j][1]+val[now]);
        }
    }
}
int main(int argc, char const *argv[])
{
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        memset(dp,0,sizeof(dp));ans=0;
        cin>>n>>c;
        for(int i=0;i<n;i++)mp[i].clear();
        for(int i=0;i<n;i++)cin>>val[i]>>tp[i];
        for(int i=1;i<n;i++)
        cin>>u>>v,mp[u].push_back(v),mp[v].push_back(u);
        dfs(0,0);
        cout<<ans<<endl;
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/Ace-MYX/p/11124414.html