poj 2342 Anniversary party 简单树形dp

本文深入解析了POJ2342题目中的树形动态规划方法,详细介绍了状态转移方程和递归求解过程,并通过代码示例展示了正确的实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//poj 2342 树形dp入门
//虽然知道这道题的状态转移方程
// dp[u][0]表示不选u这个节点的happy值
// dp[u][1]表示选u,如此一来
// v表示u的直接下级。
// dp[u][0] = sigma(max(dp[v][0],dp[v][1]));
// u没选,那他的直接下级就有两种选择
// 要么选,要么不选,取个较大值
// dp[u][1] = sigma(dp[v][0]);
// u选了,那他的直接下级就选不了了。
// 可就是做不对,wa了四五发

// 还有就是初始化的时候dp[u][1] = happy[i];
// 因为如果只选这第u个节点,那么值肯定是他本身的值

// 最后看到大牛的做法,原来是没有从
// 根开始。。。瞬间哭了


// 还有就是father[i] = i初始化这个是错的
// 要把这一行删去,又wa了好几发。。。
// 我想:如果开始每个节点都是自己节点的父节点,
// 如果是根的话,那就会每次反复的更新自己的状态
// 这样就会产生一些错误的问题,我的思考是这样

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 8000;
int n;
int dp[maxn][2];
// vector<int> mp[maxn];
int father[maxn];
int happy[maxn];
bool vis[maxn];
int root;
void init(){
	memset(dp,0,sizeof(dp));
	// for (int i=1;i<=n;i++)
		// mp[i].clear();
	// for (int i=1;i<=n;i++)//这里加上去就错了。。。
	// 	father[i] = i;
	for (int i=1;i<=n;i++){
		scanf("%d",&happy[i]);
	}
	int a,b;
	root = 0;
	while(scanf("%d%d",&a,&b)!=EOF){
		if (!a&&!b)
			break;
		father[a]=b;
		root = b;

	}
	memset(vis,0,sizeof(vis));
}

void dfs(int u){
	//dp[u][0] = 0;
	dp[u][1] = happy[u];
	vis[u] = true;
	for (int i=1;i<=n;i++){
		if (!vis[i]&&father[i]==u){
			dfs(i);
			dp[u][1] +=dp[i][0];
			dp[u][0] +=max(dp[i][1],dp[i][0]);
		}
	}
	// return max(dp[u][0],dp[u][1]);
}

void solve(){
	dfs(root);
}
void print(){
	printf("%d\n",max(dp[root][0],dp[root][1]));
}

int main(){
	//freopen("G:\\Code\\1.txt","r",stdin);
	int m;
	while(scanf("%d",&n)!=EOF){
		init();
		solve();
		print();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值