HDU4616 Game (TYOI暑期集训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;
}
原文地址:https://www.cnblogs.com/Ace-MYX/p/11124414.html