题目链接:HDU1520
题目大意:给你n个点,每个点拥有相应的权值,要求选一部分点使得他们权值和最大,要求父亲节点和孩子节点不能同时被选中。
第一次见到树形DP
注释写的很详细
AC代码
/*
2017年7月31日11:39:59
HDU1520
AC代码
*/
#include<stdio.h>
const int maxn=6000+10;
//int a[maxn];
struct Tree{
int father;//father
int child;//child
int brother;//brother
int absent,present;//缺席,出席
//求两种状态 权值更大的一种
int calc(){
return absent > present ? absent : present;
}
//初始化 present 的权值输入的时候会初始化
void init(){
father = child = brother = absent = 0;
}
}tree[maxn];
void dfs(int root){
/*
取当前节点的孩子节点
如果没有孩子,则会退出这一层
*/
int child=tree[root].child;
while(child){
//一直搜到最底层-叶子节点;
dfs(child);
/*
当父亲节点去的时候,孩子节点一定不能去。
*/
tree[root].present+=tree[child].absent;
/*
父节点不去,加上孩子节点 去和不去 两种状态的最大值
*/
tree[root].absent+=tree[child].calc();
/*
搜这个节点的兄弟节点
也就是其父亲节点下的所有孩子节点
*/
child=tree[child].brother;
}
}
int main(){
int n,l,k;
while(~scanf("%d",&n)){
/*
这里wa了好几次,仔细读题,题目中给的点是从1-7
所以存数据的时候也要从1-7开始存,一开始 我写的是0-n-1
一直wa低级错误!!!!
*/
for(int i=1;i<=n;i++){
//对每个节点的present权值初始化
scanf("%d",&tree[i].present);
//对该点的其他值进行初始化
tree[i].init();
}
/*
把l节点的父亲置为k,再把l节点的兄弟节点置为k节点的孩子节点。
更新k节点的孩子节点,如果k节点还有孩子,
那么下个孩子的兄弟节点就是l 节点
应该说清楚了吧……
*/
while(scanf("%d%d",&l,&k),l+k){
tree[l].father=k;
tree[l].brother=tree[k].child;
tree[k].child=l;
}
for(int i=1;i<=n;i++){
//只有根节点的父亲为 0
//寻找根节点
if(!tree[i].father){
dfs(i);
printf("%d\n",tree[i].calc());
break;
}
}
}
return 0;
}