树形DP入门

1、什么是树型动态规划
树型动态规划就是在“树”的数据结构上的动态规划,平时作的动态规划都是线性的或者是建立在图上的,线性的动态规划有二种方向既向前和向后,相应的线性的动态规划有二种方法既顺推与逆推,而树型动态规划是建立在树上的,所以也相应的有二个方向:
1、叶->根:在回溯的时候从叶子节点往上更新信息(一般都是从叶到根)
2、根 - >叶:往往是在从叶往根dfs一遍之后(相当于预处理),再重新往下获取最后的答案。
2、树形动态规划的优美之处
树本身至少就有“子结构”性质(树和子树);也本身就具有递归性。所以在树上DP其实是其所当然的事,相比线性动态规划来讲,转移方程更直观,更易理解。

HDU 1520 Anniversary party
题目描述:每个节点都有一个权值,子节点和父亲节点不能同时选,问最大价值。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520
解题思路:任何一个点的取舍可以看作一种决策,那么状态就是在某个点取的时候或者不取的时候,以他为根的子树能有的最大权值。分别可以用f[i,1]和f[i,0]表示节点i选或者不选。
当选了节点i时,f[i,1]+=f[j,0] //j为i的子节点
当不选节点i时,f[i,0]+=max(f[j,0],f[j,1]) //不选节点i时它的子节点可以选也可以不选

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
const int maxn=1e6+10;
int n;
ll f[maxn][2],a[maxn];
vector<int> e[maxn]; 
void dfs(int x){
	for(int i=0;i<e[x].size();i++){
		int u=e[x][i];
		dfs(u);
		f[x][0]+=max(f[u][1],f[u][0]);
		f[x][1]+=f[u][0];
	}
}

int main()
{
	int x,y;
	while(scanf("%d",&n)!=EOF){
		rep(i,1,n) scanf("%d",&a[i]),e[i].clear(),f[i][0]=0,f[i][1]=a[i];
		map<int,int> mp;
		while(1){
			scanf("%d%d",&x,&y);
			if(x==0&&y==0) break;
			e[y].pb(x);
			mp[x]=1;
		} 
		int root;
		rep(i,1,n) if(!mp[i]) root=i;
		dfs(root);
		cout<<max(f[root][0],f[root][1])<<endl;
	} 
	return 0;	
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值